The iterator was not invented by Ruby. it is widely used in various object-oriented languages. this is also true in Lisp. even so, the concept of iterator is not familiar to many people, so we will give a more detailed introduction here.
You know, the verb iterate means to do the same thing many times, so iterator is used to do the same thing many times.
When writing code, we need loops in various environments. In C, we use for or while. for example,
Char * str;
For (str = "abcdefg"; * str! = '\ 0'; str ++ ){
/* Process a character here */
}
C (...) the Syntax provides an abstract method for writing loops. However, to test whether the * str is null requires the programmer to understand the details of the internal structure of the string. this makes C look like a low-level language. more advanced languages are implemented through their more flexible iterator support. consider the following sh command line script:
#! /Bin/sh
For I in *. [ch]; do
#... Here wocould be something to do for each file
Done
All C source files and header files in the current directory will be processed. The command line shell will retrieve the file names one by one and process the details. I think this is working at a level higher than C. What do you think?
But there is more worth considering: while a language can provide an iterator for the built-in data types, we still need to go back and use low-level loop languages to implement iteration of data types defined by ourselves, which is disappointing. in the face of object programming, users often define data types one by one, so this is a very serious problem.
Therefore, all OOP Languages contain certain iterator mechanisms. Some languages provide a special class for this. Ruby allows us to define the iterator directly.
There are many useful iterators for the String type of Ruby:
Ruby> "abc". each_byte {| c | printf "<% c>", c}; print "\ n"
<A> <B> <c>
Nil
Each_byte is an iterator used for each character in the string. Each string is replaced by the local variable c. This can be translated into code similar to C...
Ruby> s = "abc"; I = 0
0
Ruby> while I <s. length
| Printf "<% c>", s [I]; I + = 1
| End; print "\ n"
<A> <B> <c>
Nil
... However, the each_byte iterator should be simpler in concept, and can work even if the String class changes suddenly in the future. one advantage of using the iterator is that such changes can still be robust. In general, it is indeed a feature of good code. (Well, please be patient. We will talk about classes right away)
Another iterator of String is each_line.
Ruby> "a \ nb \ nc \ n". each_line {| l | print l}
A
C
Nil
Using the iterator will easily replace most of C's programming effects (find line breaks, generate substrings, and so on)
The previous for statement uses the each iterator to implement the iteration function. The each of String is similar to that of each_line. Let's use the for statement to overwrite the above example:
Ruby> for l in "a \ nb \ nc \ n"
| Print l
| End
A
C
Nil
We can use the retry flow control statement to connect to the iteration loop. It will execute the iteration of the current loop from the beginning.
Ruby> c = 0
0
Ruby> for I in 0 .. 4
| Print I
| If I = 2 and c = 0
| C = 1
| Print "\ n"
| Retry
| End
| End; print "\ n"
012
01234
Nil
Yield sometimes appears in the definition of an iterator. yield moves process control to the code field passed to the iterator (this will introduce more details in the procedure object section ). the following example defines a repeat iterator that executes code fields multiple times based on the parameter settings.
Ruby> def repeat (num)
| While num> 0
| Yield
| Num-= 1
| End
| End
Nil
Ruby> repeat (3) {print "foo \ n "}
Foo
Foo
Foo
Nil
With retry, we can define an iterator with the same role as while, although it is too slow in practical applications.
Ruby> def WHILE (cond)
| Return if not cond
| Yield
| Retry
| End
Nil
Ruby> I = 0; WHILE (I <3) {print I; I + = 1}
012 nil
Do you understand what an iterator is? There are some restrictions, but you can write your own iterator. In fact, it is often convenient to define a suitable iterator for a new data type. in this case, the above example is not very useful. after understanding the class, we can discuss more practical iterators.