A detailed explanation of code blocks in Ruby and its parameter transfer _ruby topics
Source: Internet
Author: User
First, the block statement
Block declarations are enclosed in {..} or do..end after the function call. {} Is generally used for single-line statements, and do..end is used for multi-line statements.
Blocks can take parameters. Unlike function parameters, block parameters are encapsulated with ||, of course, they can take multiple parameters. How to define these parameters is actually defined inside the function, which will be described later.
Second, access to variables within the block
Variables outside the block can be accessed inside the block, that is, variables outside the block are visible inside the block, such as
sum = 0
(1..5) .each do | v |
name = 'smile' #name belongs to the variable in the block, and its visible range can only be in the block. Assume that there is no variable with the same name outside the block.
sum + = v #sum is visible inside the block
end
p sum #Output 15, sum has changed.
p name #Error! name is not accessible.
Because the variables inside and outside the block can be changed, some external variables may be accidentally modified. This is not what we want. Fortunately, after Ruby version 1.9, a safe way is provided to declare variables inside the block, add ";" after the block parameters, and put variables inside the block after ";".
name = 'outside'
sum = 0
(1..5) .each do | v; name | #nameAfter ";", multiple variables can be declared, separated by commas
name = 'inside' #name belongs to the variable inside the block, and its visible range can only be inside the block. Assume that there is no variable with the same name outside the block.
sum + = v #sum is accessible within the block
end
p sum #Output 15, sum has changed.
p name #Output outside, unchanged.
Third, the yield statement
Looking at this, it may not be quite clear how functions call blocks. Now to introduce the call of the block, the key is the yield statement. In the function body, if yield is used, the function calls the function's block.
def threeTime
yield
yield
yield
end
threeTime {p 'Hello world!'}
Is it easy to output three lines of Hello world !? You should understand now, it is the block called yield.
What is the parameter of the block? It is estimated that you have already thought of it, which is the parameter of yield. Like ordinary functions, yield can take parameters. See example
def takeBlock (p1)
if block_given? # Determine if there is a block. If you do not declare the block during yield, an error will occur, so it is better to make a judgment here.
yield (p1) # Pass p1 to the block parameter, which is the s in the block declaration below
else
p1
end
endie
takeBlock ("no block") #output "no block"
takeBlock ("no block") {| s | s.sub (/ no /, '')} #output "block"
Since yield can pass parameters to the block, and vice versa, can the block pass values to yield? The answer is yes. The value of the last sentence in the block is automatically passed to yield. See example
def nTime
i = yield # return block value on first call
(0..i) .each {| v | yield (v)} # Here yield can also be placed in a block
end
nTime do | v |
print "# {v}" if v
9 #yield number returned when called
end
#Output 1 2 3 4 5 6 7 8 9
Of course, the above example is only used as an example. In fact, no one will define it this way. A better definition is as follows:
def nTime (n)
(0..n) .each {| v | yield (v)}
end
nTime (9) do | v |
print "# {v}"
end
Let's look at the find implementation in Array
class Array
def find
for i in 0 ... size
value = self [i]
return value if yield (value)
end
return nil
end
end
[1, 3, 5, 7, 9] .find {| v | v> 5} #Find the first number greater than 5, and output 7.
Because of the appearance of blocks, many for statements are missing in Ruby, and the code looks more humane. Writing code is no longer a boring thing, but a pleasure.
Fourth, another way to pass blocks
def fun #without parameters
yield
end
proc =-> {p 'haha'}
fun & proc
#####
def fun2 (x) #with parameters
yield x
end
proc2 =-> (x) (p x)
fun2 1, & proc2
Five, instance_eval () and instance_exec ()
In Ruby, a very cool feature is provided. You can insert a code block by using Objec # instance_eval (), Objec # instance_exec () methods, make an object context probe (Context Proble), and dive into the code in the object Clips and manipulate them. With this feature, you can easily test the object's behavior and view the current state of the object.
class MyClass
def initialize
@v = 1;
end
end
obj = MyClass.new
obj.instance_eval do
puts self # => # <MyClass: 0x007fbb2d0299b0>
puts @v # => 1
end
obj.instance_exec (5) {| x | puts x * @v} # => 5
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.