List contents
First, what is block in ruby?
Block is a general term, Chinese name is also called closure, English is Closure, in the form of block, Proc and
Lambda. Proc is an object-oriented encapsulation of block, lambda is a further encapsulation of Proc.
block Writing Style
Braces + code {p'hi'} do... end, which is also a block of code
Two, block
Although everything in Ruby is an object, a block exists as a feature, not an object.
Look at the following code:
> my_array = [ 1, 2, 3, 4, 5 ] my_array.each { | number | puts number}
> my_array.each do | number | puts number end my_array.each_index { |
> index | puts "number has #{index}" }
Simply put, the following expressions of each are blocks. The example above is the block method that calls the Array object. It seems mysterious, but we can also define a block method for our class.
class MyArray
attr_accessor :my_arr
def initialize( my_arr )
@my_arr = my_arr
end
def my_each( &my_block )
for i in 0..@my_arr.length-1
my_block.call( @my_arr[i] )
end
end
a = MyArray.new( [1,2,3,4] )
a.my_each { | number | puts number }
The results are simple: 1, 2, 3, 4
Now that we've talked about customization, we can't end this way. We can be a little more complicated.
class MyArray
attr_accessor :my_arr
def initialize( my_arr )
@my_arr = my_arr
end
def my_each( &my_block )
for i in 0..@my_arr.length-1
my_block.call( @my_arr[i], i )
end
end
end
a = MyArray.new( [ 1, 2, 3, 4 ] )
a.my_each { | number, index | puts "number at #{index} has value #{number}" }
The results are as follows:
number at 0 has value 1
number at 1 has value 2
number at 2 has value 3
number at 3 has value 4
Next, I have to talk about the key word yield. Let's start with a simple example.
class MyArray
attr_accessor :my_arr
def initialize( my_arr )
@my_arr = my_arr
end
def my_yield
yield
end
end
a = MyArray.new( [ 1, 2, 3, 4 ] )
a.my_yield { puts "yield is also sexy!" }
Ignore 1, 2, 3, 4, the above example will only output yield is also sexy!, that is to say, all the content behind a.my_yield goes to my_yield, replacing yield, simple.
Start upgrading it below:
class MyArray
attr_accessor :my_arr
def initialize( my_arr )
@my_arr = my_arr
end
def my_yield
yield( @my_arr )
end
end
a = MyArray.new( [ 1, 2, 3, 4 ] )
a.my_yield {| my_tmp_arr |
puts "yield with parameter!"
my_tmp_arr.each{| number | puts number}
}
The output is as follows:
yield with parameter!
1
2
3
4
If you're not an expert, I'm sure you'll go back and review the code. What happened in my_yield? In fact, it's not difficult, as in the example above, to replace yield with @my_arr and replace my_tmp_arr with @my_arr.
Three, Proc
As mentioned earlier, Proc is Ruby's object-oriented encapsulation of blocks. In short, I define a block that I can reuse many times. Let's take an example. For example, I want to calculate the area of a rectangle.
rectangle_area = Proc.new{ | a, b | puts a * b }
rectangle_area.call( 5, 6 )
If I want to fix the long side, just input the width, then I can add a parameter:
def rectangle_area_with_length (length)
Proc.new{ | width | width * length }
end
area = rectangle_area_with_length(6)
area.call(3)
area[3]
area.class # => Proc
Four, lambda
lambda is actually a function of Ruby to create Proc.
multiply_lambda_proc = lambda { | x, y | x * y }
multiply_lambda_proc.call( 3, 4 ) # return 12
5. Differences between proc and lambda
There are two main differences:
First, lambda checks the parameters, but Proc does not.
multiply_lambda_proc = lambda { | x, y | x * y }
multiply_proc = Proc.new { | x, y | x * y }
multiply_lambda_proc.call( 3, 4, 5 ) # ArgumentError: wrong number of arguments (3 for 2)
multiply_proc.call( 3, 4, 5 ) # return 12 as normal
multiply_proc.call( 3 ) # TypeError: nil can't be coerced into Fixnum
Second, lambda returns its calling function, but Proc terminates its function.
This sentence is not very easy to understand. It is also the difference between block and lambda. Lambda is essentially a function, so it will return from lambda when it comes to return. Proc is a code that can be executed, which is equivalent to inserting a break code into the function. When the return statement is included in proc, the whole function will return.
def return_from_proc
ruby_proc = Proc.new { return "return from a Proc" }
// Equivalent to return "return from a Proc" This is equivalent to jumping out of this function.
ruby_proc.call
return "The function will NOT reach here because a Proc containing a return statement has been called"
end
def return_from_lambda
ruby_lambda = lambda { return "return from lambda" }
//Equivalent to def ruby_lambda return "return from lambda" end TherereturnIt's like jumping out of this. ruby_lambda The following statement of the function will also be executed
ruby_lambda.call
return "The function will reach here"
end
puts return_from_proc # display return from proc
puts return_from_lambda # display The function will reach here
6. How do blocks be converted into proc objects?
1.Proc.new + code block
Proc.new { |imsi| where(imsi: imsi) }
2.proc + code block (proc abbreviation)
proc { |imsi| where(imsi: imsi) }
3.lambda + Code Block
lambda{ |rs| where.not(report_status: rs) }
4. -> + Code Block (lambda abbreviation)
--> (rs) { where.not(report_status: rs) }
Summary: Block is not an object, but a code block. It can be imagined as an instance object of proc. It can only call proc once to encapsulate the block further and reuse it.
lambda's further encapsulation of proc is actually a function, more rigorous, that checks parameters