# Code source: http://rubyer.me/blog/917. you can easily learn four kinds of closures of Ruby: blocks, procs, Lambdas, and methods.
# Firstclass array def iterate! Self. each_with_index do | N, I | self [I] = yield (n) end endendarray = [1, 2, 3, 4] array. iterate! Do | x ** 2 endputs array. Inspect # => [1, 4, 9, 16] # secondclass array def iterate! (& Code) # iterate! Pass a parameter & code, which indicates that this parameter is a block. Self. each_with_index do | N, I | self [I] = code. Call (n) # In iterate! Yield is not used but a call. End endendarray. iterate! Do | n ** 2 endputs array. Inspect # Third # --- the only difference between the proc procs process block and proc is that the block cannot be saved as proc, which is one-time. Square = Proc. New do | n ** 2 endclass array def iterate! (CODE) # Now these is not & code, not null, but code !! # Note: It is not in iterate! The parameter header is added because proc is just a common class and does not require special processing. Self. each_with_index do | N, I | self [I] = code. Call (n) end endendarray. iterate! Square puts array. Inspect
Source: http://rubyer.me/blog/917
First, open array and add it to iterate! Method. The method name is! It indicates a dangerous method at the end. Now we may be using collect! Use iterate!
Unlike the attribute, you do not need to specify the block name in the method, but use yield to call it. Yield executes the code in the block. At the same time, note how we pass N (number currently processed by each_with_index) to yield. The parameter passed to yield corresponds to the parameter (| part of the block ). Now N can be called by block and N ** 2 will be returned in yield call.
The entire call is as follows:
1. An array composed of integers calls iterate!
2. When yield is called, set N (1 for the first time, 2 for the second time ,...) Pass to block
3. Block N ** 2. Because it is the last row, it is automatically returned as a result.
4. Yield gets the block result and overwrites the value to the array (self is used here. In the definition of Class and module, self represents this class or this module object, expanded reading: http://fuliang.iteye.com/blog/272370 ).
5. Each object in the Data performs the same operation.
def callbacks(procs) procs[:starting].call puts "Still going" procs[:finishing].callendcallbacks(:starting => Proc.new { puts "Starting" }, :finishing => Proc.new { puts "Finishing" })# => Starting# => Still going# => Finishing
1. (: Starting => Proc. new {puts "starting"},: Finishing => Proc. new {puts "Finishing"}) a hash table or a string symbol (Symbol) is defined here ). (A symbol object is always starting, for example:foo
Or:foo_bar
. Its role is to represent a name, and its biggest role is to make a hash partition (key), for example{ :foo => 1, :bar => 2 }
Here, we only need a specific name and do not need to use string objects. Use the symbol notation to improve the performance of both products and products .)
2. Starting => Proc. New {puts "starting"} The Key key is starting, and the key value is a procs process.
3. The procs [: Starting]. Call directly calls the procs process stored in procs [: Starting ].
BTW: When will blocks be used instead of procs? I generally think like this:
1. Block: The method splits an object into many fragments, and you want your users to interact with these fragments.
2. Block: You want to automatically run multiple statements, such as database migration ).
3. Proc: You want to reuse a piece of code multiple times.
4. Proc: The method has one or more callback methods (callbacks ).
If not, continue tomorrow.