为什么Ruby使用yield?

mka*_*mka 14 ruby

我是Ruby的新手.我使用了很多允许高阶函数的C#和JavaScript,我通常每天都使用它们.

Ruby虽然对我来说有点奇怪.一个each函数可能看起来像:

def each
    @items.each do |item|
        yield(item)
    end
end

items.each { |item| puts item }
Run Code Online (Sandbox Code Playgroud)

然而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 }
Run Code Online (Sandbox Code Playgroud)

甚至:

def each(&proc)
    @items.each do |item|
        proc.call item
    end
end

# No difference in syntax.
items.each { |item| puts item }
Run Code Online (Sandbox Code Playgroud)

这与大多数其他语言不同,只是几个字符更长.一切似乎都在使用,而不是显式传入一个块yield.

yield本身似乎疯狂,神奇,神秘.毕竟,它会转到呼叫的起源并在呼叫后立即抓住一个阻止.这看起来很古怪和不自然,我不知道这个功能在另一种语言中有任何平行.

那有什么处理yield

yfe*_*lum 14

产量是Syntax Sugar

这个收益率的例子:

def do_something_for_each(array)
  array.each do |el|
    yield(el)
  end
end
Run Code Online (Sandbox Code Playgroud)

只是语法糖:

def do_something_for_each(array, &block)
  array.each do |el|
    block.call(el)
  end
end
Run Code Online (Sandbox Code Playgroud)

选择你喜欢的语法并随之运行.

  • @LBg:捕获块(使用&block)非常昂贵。它需要创建一个对象,并且该对象必须能够超出其范围。例如,do_something可以存储它并在以后调用它。 (2认同)

Tod*_*obs 6

Yield将对象传递给方法块

[收益率]转到呼叫的起源并在呼叫后立即抓住一个阻止.

并不是的.yield将参数传递给块; 它不会"抓住一块"或用它做任何事情.换句话说,这个:

def foo; yield self; end
foo { |x| x.inspect }                                       
# => "main"
Run Code Online (Sandbox Code Playgroud)

这里,yield除了将参数传递给传递给foo方法的块之外,没有做任何事情.每个Ruby方法都支持一个可选块 - 除非块实际上是强制性的 - 所以唯一的"魔力"是该语言允许块传递,即使它没有被明确声明为方法签名的一部分.

更多例子

要在操作中查看此隐式签名,请考虑以下事项:

def foo; puts block_given?; end
foo { |x| x.inspect }
Run Code Online (Sandbox Code Playgroud)

这将打印"true"并返回nil,这是该puts方法的预期返回值.

当然,没有yield阻止根本不做任何事情.例如:

def foo; end
foo { |x| x.inspect }
# => nil
Run Code Online (Sandbox Code Playgroud)