枚举器yielder.yield VS Proc.yield

Jam*_*ang 4 ruby yield enumerator

我最近开始阅读"Programming Ruby 1.9&2.0"一书.它显示了显式枚举器的技巧

triangular_numbers = Enumerator.new do |yielder|
number = 0
count = 1
    loop do
        number += count
        count += 1
        yielder.yield number
    end
end
5.times { print triangular_numbers.next, " " }
puts
Run Code Online (Sandbox Code Playgroud)

我想知道为什么这个yielder.yield会暂时离开循环并返回number的值,直到创建下一个枚举器对象.它似乎与循环块内的产量的通常情况不同.我查看了APIdock,发现Proc.yield()的源代码与Proc.call()相同.对于Enumerator类中的Yielder对象,Yielder已覆盖yield().但是为什么yielder.yield会暂时离开循环块?

参考: APIdock Yielder yield(), Ruby MRI rb_proc_call

Max*_*Max 8

您将Ruby的yield 语句与Enumerator :: Yielder的yield 方法和Proc的yield 方法混淆.它们的拼写可能相同,但它们完全不同.

声明

yield语句没有接收者.在方法内部,它意味着"立即运行块".如果未附加块,则会发生错误.它并不总是有一个参数,因为有时你只想运行块.

def foo
  yield :bar
end
foo # LocalJumpError
foo { |x| puts x } # bar
Run Code Online (Sandbox Code Playgroud)

枚举:: Yielder

对于一个yielder来说,yield几乎总是有争议.那是因为它意味着<<"下次有人打电话next给我时,给他们这个价值".

Enumerator.new { |yielder| yielder.yield 3 }.next # 3
Enumerator.new { |yielder| yielder << 3 }.next # same thing
Run Code Online (Sandbox Code Playgroud)

我认为使用它<<来避免与yield语句混淆是一个好主意.

PROC

Procs和lambdas基本上都是函数.yield这里的意思与call"只是调用函数"相同.您可以给它一个参数或不参数,具体取决于proc的定义方式.没什么好看的.

proc { |x| puts x }.yield(:bar) # bar
proc { |x| puts x }.call(:bar) # same thing as previous line
Run Code Online (Sandbox Code Playgroud)

我认为使用它call来避免与yield语句混淆是一个好主意.