来源codecademy
一.Proc类
Proc Syntax
Procs are easy to define! You just call Proc.new and pass in the block you want to save. Here’s how we’d create a proc called cube that cubes a number (raises it to the third power):
cube = Proc.new { |x| x ** 3 }
We can then pass the proc to a method that would otherwise take a block, and we don’t have to rewrite the block over and over!
[1, 2, 3].collect!(&cube)
# ==> [1, 8, 27]
[4, 5, 6].map!(&cube)
# ==> [64, 125, 216]
(The .collect! and .map! methods do the exact same thing.)
The & is used to convert the cube proc into a block (since .collect! and .map! normally take a block). We’ll do this any time we pass a proc to a method that expects a block.
Proc Syntax
Why bother saving our blocks as procs? There are two main advantages:
- Procs are full-fledged objects, so they have all the powers and abilities of objects. (Blocks do not.)
Unlike blocks, procs can be called over and over without rewriting them. This prevents you from having to retype the contents of your block every time you need to execute a particular bit of code.
examples:
cube = Proc.new { |x| x ** 3 }
[1, 2, 3].map(&cube)
# [1, 8, 27]
def greeter
yield
end
phrase = Proc.new { puts "Hello there!" }
greeter(&phrase)
Call Method
Calling a proc with a method isn’t too tricky. However, there’s an even easier way.
Unlike blocks, we can call procs directly by using Ruby’s .call method. Check it out!
test = Proc.new { # does something }
test.call
# does that something!
使用Symbol调用Proc
Now that you’re learning some of the more complex parts of the Ruby language, you can combine them to work some truly arcane magicks. For instance, remember when we told you that you could pass a Ruby method name around with a symbol? Well, you can also convert symbols to procs using that handy little &.
trings = ["1", "2", "3"]
nums = strings.map(&:to_i)
# ==> [1, 2, 3]
个人理解:就是调用已用对象方法,使用&:to_s格式调用
二.Lambda类
Lambda Syntax
Like procs, lambdas are objects. The similarities don’t stop there: with the exception of a bit of syntax and a few behavioral quirks, lambdas are identical to procs.
lambda { puts "Hello!" }
lambda { |param| block }
Proc.new { puts "Hello!" }
例子:
strings = ["leonardo", "donatello", "raphael", "michaelangelo"]
symbolize = lambda {|x| x.to_sym}
symbols = strings.collect(&symbolize)
print symbols
三.Proc vs Lambda
If you’re thinking that procs and lambdas look super similar, that’s because they are! There are only two main differences.
- First,a lambda checks the number of arguments passed to it, while a proc does not. This means that a lambda will throw an error if you pass it the wrong number of arguments, whereas a proc will ignore unexpected arguments and assign nil to any that are missing.
- Second, when a lambda returns, it passes control back to the calling method; when a proc returns, it does so immediately, without going back to the calling method.
To see how this works, take a look at the code in the editor. Our first method calls a proc; the second calls a lambda.
def batman_ironman_proc
victor = Proc.new { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_proc
def batman_ironman_lambda
victor = lambda { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_lambda
结果:
Batman will win!
Iron Man will win!
原因就是上面说的第二点, Proc运行到return后直接返回数据,结束当前方法. Lambda.call之后把值带回方法,然后方法继续运行,返回了最后一个数据值”Iron Man will win!”