The use of the return, break, and next keywords involves the issue of jumping out of scope, but their difference lies in the different scope of the purpose of different keywords jumping out, because there are code blocks that cause some needs Pay special attention.
return
Common ways
In general, the return statement has the same meaning as everyone understands.
def m1 param
if param == 1
return ‘returned 1’
end
‘Returned default
value ‘# According to the Ruby language specification, the result of the last executed statement is returned as the return value.
, Retu rn is optional
end
m1 (1) # => returned 1
m1 (2) # => returned default value
The situation is slightly different when there is an exception caught assurance:
def m1
‘Return default’
ensure
puts ‘I am sure that it will be here!’
end
m1 # => return default
In this case, before the ensure statement, no matter whether it is returned with return or not, the m1 method will return the value before ensure. The ensure statement just ensures that the subsequent code block puts 'I am sure that it will be here!', But Will not return from here. The situation is different if return is used as the return value in the ensure statement. Examples are:
def m1
return ‘return default’
ensure
return ‘I am sure that it will be here!’
end
m1 # => I am sure that it will be here!
Regardless of whether the return is displayed before ensure, it will only return the value after ensure.
In the case of code block intervention, it will be different again:
def m1
p ‘start ...‘
proc do
p ‘block start’
return
p ‘block end’
end.call
p ‘end ...‘
end
m1
# Output results:
#
# "start ..."
# "block start"
This should be expected, look at the next one:
def m1
p ‘start ...‘
-> do
p ‘block start’
return
p ‘block end’
end.call
p ‘end ...‘
end
m1
# Output results:
#
# "start ..."
# "block start"
# "end ..."
There is an extra line "end ..." here. Why? This is the biggest difference between Proc and Lambda. The return scope of the return statement among them is different. Proc will directly jump out of the entire method call. Lambda will only jump out of its scope and return to the method to continue execution. This requires special attention. (In break, Proc and Lambda are the same way to return and return, so I won't repeat them later.)
break
First look at a simple small example:
result = [1, 2, 3, 4, 5] .map do | i |
i * 2
end
p result # => [2, 4, 6, 8, 10]
There is nothing strange about this, so take a look at the following to guess what its output is?
result = [1, 2, 3, 4, 5] .map do | i |
break if i> 3
i * 2
end
# FLAG
p result
Is it [1, 2, 3, nil, nil]? Or [1, 2, 3]? what is this else? The answer is nil, because after executing break, I jumped directly to FLAG, that is, I jumped out of the map method, and the statements in the map method were not executed, resulting in no return value. To verify that this idea is correct, we can use Ruby The language break can be verified with the characteristics of the return value:
result = [1, 2, 3, 4, 5] .map do | i |
break ‘returned break’ if i> 3
i * 2
end
p result # => "returned break"
Here we can prove that our guess is correct. Although the above illustrates the problem, it should not be easy to understand yet. Let's define a code block and explain it again:
def m1
p ‘start in m1 ...‘
m2 do # code block
p ‘start in block in m1 ...‘
p ‘end in block in m1 ...‘
end
p ‘end in m1 ...‘
end
def m2 & block
p ‘start in m2 ...‘
block.call
p ‘end in m2 ...‘
end
m1
# Output results:
#
# "start in m1 ..."
# "start in m2 ..."
# "start in block in m1 ..."
# "end in block in m1 ..."
# "end in m2 ..."
# "end in m1 ..."
Then we add break to the block in m1 to see the execution result:
def m1
p ‘start in m1 ...‘
m2 do # code block
p ‘start in block in m1 ...‘
break
p ‘end in block in m1 ...‘
end
p ‘end in m1 ...‘
end
def m2 & block
p ‘start in m2 ...‘
block.call
p ‘end in m2 ...‘
end
m1
# Output results:
#
# "start in m1 ..."
# "start in m2 ..."
# "start in block in m1 ..."
# "end in m1 ..."
You can see that the last line of code in the code block was not executed, and the last line of m2 was not executed, because this line was not executed, which caused the map in the second example of break to return no value. To summarize, the break in the code block will directly jump out of the called method (m2), and continue to execute the remaining statements in this method (m1) in the method (m1) that declares the code block.
next
The next keyword is similar to continue in other languages, and it basically works similarly to continue.
def m1
p ‘start in m1 ...‘
m2 do # code block
p ‘start in block in m1 ...‘
next
p ‘end in block in m1 ...‘
end
p ‘end in m1 ...‘
end
def m2 & block
p ‘start in m2 ...‘
block.call
p ‘end in m2 ...‘
end
m1
# Output results:
#
# "start in m1 ..."
# "start in m2 ..."
# "start in block in m1 ..."
# "end in m2 ..."
# "end in m1 ..."
Just skipping the last line of code, that's how next works. Let's take a look at the break example again. If we write next, what is the result? If you fully understand what is written above, I believe you can already calculate the result in your brain:
result = [1, 2, 3, 4, 5] .map do | i |
next if i> 3
i * 2
end
p result # => [2, 4, 6, nil, nil]
The next statement can also return a value:
result = [1, 2, 3, 4, 5] .map do | i |
next ‘next’ if i> 3
i * 2
end
p result # => [2, 4, 6, "next", "next"]
other
For return, in the method, both can be used in the code block, and break and next can only be used in the code block (also can be used in the loop structure, but generally it is also expressed in the form of code blocks), if in the method Calling both will prompt a syntax error, which is:
def m1
return # OK
break # Invalid break, compile error (SyntaxError)
next # Invalid next, compile error (SyntaxError)
end
in conclusion
In most cases, return is no different from other languages. You need to pay attention to details in ensure and two different code blocks of Proc and Lambda.
Break needs to be noted in code blocks with method nested calls, it always returns to the method that called the code block method (a bit of a wrap around).
next The most honest, basically no need to pay attention.
In the end, not only return can return a value, both break and next can return a value.
This article is compiled and compiled by OneAPM engineers. OneAPM is an emerging leader in China's basic software field, which can help enterprise users and developers easily realize: slow program code and real-time fetching of SQL statements. For more technical articles, please visit the official OneAPM technical blog.
Statement breaks and returns in Ruby