开发者

Why is the parameter of this method a lambda and how does it work

Taken from Programming ruby 1.9 book:

def my_while(cond, &body)
 while cond.call
   body.call
 end
end

a=0

my_while -> { a < 3 } do
  puts a
  a += 1
end

produces:

0

1开发者_如何学Python

2


The method expects an explicit parameter cond, and this "condition" is assumed to be a lambda/proc (the assumption is made by relying on cond.call to succeed) and has to be passed to the method my_while explicitly. The & syntax captures a method's block (if present) in a variable by implicitly converting it to a Proc object (see 'The ampersand').

Blocks are not real objects in Ruby and thus have to be converted by using the ampersand syntax. Once the block is bound to a Proc, you can send the call message on it as on any other proc/lambda.

The -> syntax is short for lambda, which converts a block to a Proc object (explicitly). There is also a slight difference between using lambda and Proc.new. Again, the wikibook:

Actually, there are two slight differences between lambda and Proc.new.

First, argument checking. The Ruby documentation for lambda states: Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.

Second, there is a difference in the way returns are handled from the Proc. A return from Proc.new returns from the enclosing method (acting just like a return from a block, more on this later):

def try_ret_procnew
  ret = Proc.new { return "Baaam" }
  ret.call
  "This is not reached"
end

# prints "Baaam"
puts try_ret_procnew

While return from lambda acts more conventionally, returning to its caller:

def try_ret_lambda
  ret = lambda { return "Baaam" }
  ret.call
  "This is printed"
end

# prints "This is printed"
puts try_ret_lambda

With this in light, I would recommend using lambda instead of Proc.new, unless the behavior of the latter is strictly required. In addition to being way cooler a whopping two characters shorter, its behavior is less surprising.


The piece -> { a < 3 } is a shortcut for a lambda term (which was introduced with ruby 1.9). This is the first parameter passed to your method (i.e. cond) while the block afterwards is assigned to body. The lambda is then executed inside your method via cond.call.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜