我是Ruby新手。我使用了很多允许高阶函数的C#和JavaScript,我通常每天都使用它们。
但是Ruby对我来说似乎有点奇怪。each
函数可能如下所示:
def each
@items.each do |item|
yield(item)
end
end
items.each { |item| puts item }
然而Ruby也对高阶函数有一些支持。以上内容可以改写为:
def each(proc)
@items.each do |item|
proc.call item
end
end
items.each -> (item) { puts item } # Or...
items.each lambda { |item| puts item }
甚至:
def each(&proc)
@items.each do |item|
proc.call item
end
end
# No difference in syntax.
items.each { |item| puts item }
这与大多数其他语言相比更接近,而且只是几个字符。一切似乎都使用yield
。
yield
本身似乎疯狂,神奇,神秘。毕竟,它会转到呼叫的起源并在呼叫后立即抓住一个阻止。这看起来很古怪和不自然,我不知道这个功能在另一种语言中有任何平行。
那么与yield
的交易是什么?
答案 0 :(得分:14)
这个收益率的例子:
def do_something_for_each(array)
array.each do |el|
yield(el)
end
end
只是语法糖:
def do_something_for_each(array, &block)
array.each do |el|
block.call(el)
end
end
选择您喜欢的语法并随之疯狂。
答案 1 :(得分:6)
[收益率]转到呼叫的原点并在通话结束后立即抓住一个阻止。
不是真的。 yield
将参数传递给块;它不会“抓住一块”或用它做任何事情。换句话说,这个:
def foo; yield self; end
foo { |x| x.inspect }
# => "main"
这里,yield
除了将参数传递给传递给foo
方法的块之外没有做任何事情。每个Ruby方法都支持一个可选块 - 除非块实际上是强制性的 - 所以唯一的“魔力”是语言允许块传递,即使它没有被明确声明为方法签名的一部分。
要查看此隐式签名,请考虑以下事项:
def foo; puts block_given?; end
foo { |x| x.inspect }
将打印“true”并返回nil
,这是puts
方法的预期返回值。
当然,如果没有yield
,该块根本不会做任何事情。例如:
def foo; end
foo { |x| x.inspect }
# => nil
答案 2 :(得分:4)
yield
的一个优点是它还允许您使用next
(例如continue
)和break
。在其他语言中,对于next
,您可能必须使用return
,对于break
,您可能必须(ab)使用例外。对这些操作提供内置支持可能更好。