Document directory
Iterator:
1,A ruby iterator is a simple method that can receive code blocks (for example, the each method is an iterator ). Feature: if a method contains yield calls, this method must beIterator
2. There is a following transfer relationship between the iterator method and the block: The block is passed to the iterator method as a special parameter, the iterator method can pass the parameter value into the block when calling the code block using yield.
3. In fact, the iterator function is a callback! The class to which the iterator method belongs is only responsible for traversing the elements to be traversed, and the processing of the elements is implemented through the callback code block.
4. The container objects (such as arrays, ranges, and hash objects) in Ruby contain two simple iterators: each and collect. Each can be considered as the simplest iterator, which calls blocks for each element of the set. Collect: Pass the elements in the container to a block. After processing in the block, a new array containing the processing result is returned.
Two classic examples:
# Define an apple class Apple # define the apple class constructor def initialize (name, color, weight) @ name = Name; @ color = color; @ Weight = weight; end # three attributes ATTR: Name ATTR: Color ATTR: weight are defined using memory # A show method is defined. This show method can be used as an apple iterator def show yield: Name, @ name yield: color, @ color yield: weight, @ weight end # create an apple instance Apple = apple. new ("Red Apple", "Red", "0.4") # use Apple's show iterator apple. show do | Name, value | puts "this apple" + name. to_s + "variable value:" + value. to_s end
Class array # Add a find method def find for Array # Use for loop to iterate all array elements for I in 0... size value = self # pass the array element value into the code block when calling yield # Return Value of the code block after calling (Boolean value) return the return value if yield value end return nil end # Use the find method puts of the array [1, 3, 5, 7, 9]. find {| v | V * V> 30}
Block and closure:
1. Do... end this is a block, code block, or anonymous method.
2. Block: Just a piece of code, which is equivalent to an anonymous function; closures: A piece of code that can be passed as a parameter to other methods.
3. Four Closures of Ruby: blocks, procs, Lambdas, and methods. It is the most powerful part of Ruby and the most confusing. (Understand the four closures of Ruby: blocks, procs, Lambdas, and methods. Http://rubyer.me/blog/917)
4,
----------------------------------------------------------
Implement iterator
----------------------------------------------------------
From http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html
Chinese from http://blog.csdn.net/ruby_cn/article/details/192094
Implementing iterators
Implement iterator
A ruby iterator is simply a method that can invoke a block of code. at first sight, a block in ruby looks just like a block in C, Java, or Perl. unfortunately, in this case looks are deceiving --- a ruby block is a way of grouping statements, but not in the conventional way.
A ruby iterator is a simple method that can receive code blocks (for example, the each method is an iterator ).At first glance, the blocks in ruby are the same as those in C, Java, and Perl, but they are actually different.
First, a block may appear only in the source adjacent to a method call; the block is written starting on the same line as the method's last parameter. second, the code in the block is not executed at the time it is encountered. instead, Ruby remembers the context in which the block appears (the local variables, the current object, and so on), and then enters the method. this is where the magic starts.
First, the block in the source code is closely tied to the method call, and is written on the same line as the last parameter of the method. Secondly, this block will not be executed immediately. Ruby will first remember the context of the block (local variables, current object, etc.) and then enter the method. This is also the starting point of magic.
Within the method, the block may be invoked, almost as if it were a method itself, using the yield statement. whenever a yield is executed, it invokes the code in the block. when the block exits, control picks back up immediately after the yield. [programming-language buffs will be pleased to know that the keyword yield was chosen to echo the yield function in liskov's language Clu, A language that is over 20 years old and yet contains features that still haven't been widely exploited by the clu-less.] let's start with a trivial example.
In the method, this block will be called and executed using yield. Just like this block is the method itself, this block will be called whenever yield is executed in the method. After this block is executed and exited, the control will be handed over to the statement after yield.(Yield comes from a language with more than 20 years of history: Clu). Let's look at a small example.
def threeTimes yield yield yieldendthreeTimes { puts "Hello" }
produces:HelloHelloHello
The block (the code between the braces) is associated with the call to the method threetimes. within this method, yield is called three times in a row. each time, it invokes the code in the block, and a cheery greeting is printed. what makes blocks interesting, however, is that you can pass parameters to them and receive values back from them. for example, we cocould write a simple function that returns Members of the Fibonacci series up to a certain value. [The basic maid series is a sequence of integers, starting with two 1's, in which each subsequent term is the sum of the two preceding terms. the series is sometimes used in sorting algorithms and in analyzing natural phenomena.]
This block (defined in two braces) is assigned to the threetimes method. In this method, yield executes three times and calls the given block each time it executes, print a welcome statement. What makes the block interesting is that you can pass parameters to the block and get results from the block. In the following example, we will get a number smaller than a specified number of strings worth using the Fibonacci algorithm.
def fibUpTo(max) i1, i2 = 1, 1 # parallel assignment while i1 <= max yield i1 i1, i2 = i2, i1+i2 endendfibUpTo(1000) { |f| print f, " " }
produces:1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
In this example, the yield statement has a parameter. this value is passed to the associated block. in the definition of the block, the argument list appears between vertical bars. in this instance, the variable F has es the value passed to the yield, so the Block prints successive members of the series. (This example also shows parallel assignment in action. we'll come back to this on page 75 .) Although it is common to pass just one value to a block, this is not a requirement; a block may have any number of arguments. what happens if a block has a different number of parameters than are given to the yield? By a staggering coincidence, the rules we discuss under parallel assignment come into play (with a slight twist: multiple parameters passed to a yield are converted to an array if the block has just one argument ).
In this example, yield receives a parameter, which is passed to the specified block during execution. In the block definition, parameters are enclosed by two vertical bars and placed at the beginning. In this example, F is used to receive parameters passed by yield. Therefore, this block can print this sequence. A block can accept any parameter. What if the number of parameters in a block is different from that in yield? Coincidentally, this is the same as the principle we mentioned in parallel assignment (if a block only receives one parameter while yield provides more than one parameter, these parameters will be converted into an array .)
The parameter passed to a block can be a local variable. If so, the new value of this local variable (if modified in the block) it will be retained after the block exits, which may have some side effects, but there is a performance test rate.
Parameters to a block may be existing local variables; if so, the new value of the variable will be retained after the block completes. this may lead to unexpected behavior, but there is also a performance gain to be had by using variables that already exist. [For more information on this and other ''gotchas, ''see the list beginning on page 127; more performance information begins on page 128.]
A block may also return a value to the method. the value of the last expression evaluated in the block is passed back to the method as the value of the yield. this is how the find method used by class array works. [The find method is actually defined in module enumerable, which is mixed into class array.] its implementation wocould look something like the following.
A block can also return a result to the method that calls it. The value of the last expression in this block will be returned to the method, and the find method in array works like this.(Find inEnumerable
Is inserted into the class.Array
)
class Array def find for i in 0...size value = self[i] return value if yield(value) end return nil endend[1, 3, 5, 7, 9].find {|v| v*v > 30 }»7
This passes successive elements of the array to the associated block. if the block returns true, the method returns the corresponding element. if no element matches, the method returns nil. the example shows the benefit of this approach to iterators. the array class does what it does best, accessing array elements, leaving the application code to concentrate on its particle requirement (in this case, finding an entry that meets some mathematical criteria ).
In this usage, the Array Passes continuous elements to the specified block. If this block returns true, this method returns the current corresponding element value. If there is no matching value, Nil is returned. This method shows the benefits of the iterator. The array class only serves as its own and accesses the array elements, while the application code only focuses on special requirements.
Some iterators are common to various types of Ruby collections. we 've looked at find already. two others are each and collect. each is probably the simplest iterator --- all it does is yield successive elements of its collection.
The collection objects in Ruby also contain some other common iterators, two of which are each and collect. Each can be considered as the simplest iterator, which calls blocks for each element of the set.
[ 1, 3, 5 ].each { |i| puts i }produces:135
The each iterator has a special place in Ruby; on page 85 We'll describe how it's used as the basis of the language's for loop, and starting on page 102 we'll see how defining an each method can add a whole lot more functionality to your class for free.
Another common iterator is collect, which takes each element from the collection and passes it to the block. The results returned by the block are used to construct a new array. For instance:
The other is collect, which is similar to each. It passes the elements in the set to a block and returns a new array containing the processing result after being processed in the block.
["H", "A", "L"].collect { |x| x.succ } » ["I", "B", "M"]
Others:
Iterators: Ruby User Manual: http://guides.ruby.tw/ruby/iterators.html
Ruby | http://blackanger.blog.51cto.com/140924/23876/ of block and iterator
Deep understanding of blocks, procs and Lambdas http://blackanger.blog.51cto.com/140924/123034
Implement iterator http://free-dem.iteye.com/blog/218123 IN RUBY