在 Ruby 的上下文中, yield这个词并没有真正的特殊含义。它的含义与其他所有编程语言或编程和计算机科学中的含义相同。
当某种执行上下文将控制流交给不同的执行上下文时,通常使用它。例如,在 Unix 中,sched_yield
一个线程可以使用一个函数将 CPU 让给另一个线程(或进程)。对于协程,该术语yield
通常用于将控制从一个协程转移到另一个协程。在 C# 中,有一个yield
关键字,迭代器方法使用该关键字将控制权交给迭代方法。
Enumerator::Yielder#yield
事实上,最后一个用法与您所询问的 Ruby中方法的用法完全相同。调用此方法将暂停枚举器并放弃对枚举方法的控制。
例子:
fibs = Enumerator.new do |y|
a, b = 0, 1
y.yield a
loop do
y.yield b
a, b = b, a + b
end
end
puts fibs.next # 0
puts fibs.next # 1
puts fibs.next # 1
puts fibs.next # 2
puts fibs.next # 3
puts fibs.next # 5
puts fibs.next # 8
puts fibs.next # 13
puts fibs.next # 21
如您所见,有一个无限循环。显然,如果这个循环只是自己运行,它就没有多大用处。但由于每次调用该yield
方法时,它都会放弃控制权,直到再次调用它,这将一一生成斐波那契数,本质上表示所有斐波那契数的无限长列表。
还有另一种方法,Fiber.yield
,它具有类似的目的。(事实上,我已经在上面描述了它,因为Fiber
它只是 Ruby 对协程的名称。)在 aFiber
中,您调用Fiber.yield
将控制权交还给最初将控制权交给您的执行上下文。
最后,有一个yield
关键字,在方法体中使用它来放弃对传递给方法的块的控制。
请注意,至少在这种Enumerator
情况下(即第一个示例),您可以另外解释yield
为产生,因为Enumerator
每次调用时都会产生一个新值yield
。