将块传递给方法 - Ruby

3

我对传递 block 有一个小问题。

def a_method(a, b)
  a + yield(a, b)
end

这个很好用。

k = a_method(1, 2) do |x, y| 
  (x + y) * 3 
end
puts k

但这样做是行不通的。
puts a_method(1, 2) do |x, y| 
  (x + y) * 3 
end
# LocalJumpError: no block given (yield)

有人能够友好地向我解释这个吗?

谢谢。这个例子摘自Paolo Perrotta的《Ruby元编程》。非常好的书。


2个回答

5
< p > do..end和花括号之间的区别在于花括号绑定到最右边的表达式,而do..end绑定到最左边的表达式。请看以下示例:

def first(x=nil)
  puts "  first(#{x.inspect}): #{block_given? ? "GOT BLOCK" : "no block"}"
  "f"
end

def second(x=nil)
  puts "    second(#{x.inspect}): #{block_given? ? "GOT BLOCK" : "no block"}"
  "s"
end

first second do |x| :ok end #   second(nil): no block
                            # first("s"): GOT BLOCK

first second {|x| :ok }     #   second(nil): GOT BLOCK
                            # first("s"): no block

在第一种情况下,使用do..end创建的块将绑定到第一个函数(最左边)。在第二种情况下,使用花括号创建的块将绑定到第二个函数(最右边)。
通常,如果有两个函数和一个块,使用括号是一个好主意-只为了可读性和避免错误。
很容易意外地将块传递给puts方法,就像你的问题中一样。

-1

这是因为该块被传递给了puts而不是a_method
应该这样做:

puts (a_method(1, 2) { |x, y| (x + y) * 3 })

# if you want to keep it multilines
puts (a_method(1, 2) { |x, y|
  (x + y) * 3
})

你好,能给我一个使用 do..end 的例子吗?我之前试过用花括号,但是还在尝试如何使用 do..end。 - revolver
我一直在搜索,但没有找到关于这个问题的任何信息。也许 puts 不应该在内部有 do...end(这是有道理的,因为它不应该显示多行内容)?即使是多行块,您仍然可以使用大括号。 - Samy Dindane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接