为什么Ruby使用yield?
我是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
本身似乎疯狂,神奇,神秘。 毕竟,它会转到呼叫的起源并在呼叫后立即抓住一个阻止。 这看起来很奇怪和不自然,我不知道这个function在另一种语言中有任何平行。
那么yield
多少呢?
Yield将对象传递给方法块
[收益]转到呼叫的起源并在呼叫后立即抓住一个阻止。
并不是的。 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
产量是Syntax Sugar
这个收益率的例子:
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
选择你喜欢的语法并随之运行。
yield
一个优点是它还允许你使用next
(如continue
)和break
。 在其他语言中,对于next
语言,您可能必须使用return
,而对于break
,您可能必须(ab)使用exception。 对这些类型的操作提供内置支持可能更好。
在大多数情况下,使用yield在方法中执行块。
该块直接传递给方法,然后该方法可以使用yield关键字回调该块。
def a_method(a, b) a + yield(a, b) end a_method(1, 2) {|x, y| (x + y) * 3 } # => 10
当您回调该块时,您可以为其参数提供值,就像调用方法时一样。 此外,与方法一样,块返回它评估的最后一行代码的结果。