目前,我正在阅读 David A. Black 所著的《The Well-Grounded Rubyist》,我被困在第 10.9 章(枚举器和可枚举性的下一个维度)。我的问题是关于 yield
方法。
在 Ruby 上下文中,yield
一词的含义是什么?我的母语是俄语,谷歌翻译向我展示了一堆翻译变体,这让我感到困惑。其中一些是:放弃、带来、投降(放弃)、生产 >、同意、遵守等等。
UPD:请注意以下事实:我正在尝试理解 Enumerator::Yielder#yield 方法,但不是 yield
关键字本身。
UPD_2:我发现了一篇关于枚举器的有趣文章:“Lazy Ruby 中的枚举器”。
Currently, I'm reading "The Well-Grounded Rubyist" by David A. Black, and I'm stuck at chapter 10.9 (Enumerators and the next dimension of enumerability). My question is about the yield
method.
What is the meaning of the word yield
in the Ruby context? My native language is Russian, and Google Translate shows me a bunch of translation variants, that are confusing me. Some of them are: give, bring, surrender (give up), produce, agree, comply and many others.
UPD: please, pay attention to the fact, that I'm trying to understand the meaning of the Enumerator::Yielder#yield method, but not the yield
keyword itself.
UPD_2: I've found an interesting article about Enumerators: "Lazy Enumerators in Ruby".
发布评论
评论(6)
yield 这个词在 Ruby 上下文中实际上没有任何特殊含义。它的含义与其他所有编程语言或一般的编程和计算机科学中的含义相同。
当某种执行上下文将控制流交给不同的执行上下文时,通常会使用它。例如,在 Unix 中,有一个 sched_yield 函数,线程可以使用该函数将 CPU 交给另一个线程(或进程)。对于协程,术语“yield”通常用于将控制从一个协程转移到另一个协程。在 C# 中,有一个
yield
关键字,迭代器方法使用该关键字将控制权交给迭代方法。事实上,最后一个用法与 的用法完全相同Ruby 中的
Enumerator::Yielder#yield
方法,您正在询问该方法。调用此方法将挂起枚举器并将控制权交给枚举方法。示例:
如您所见,存在无限循环。显然,如果这个循环只是自己运行的话,它并没有多大用处。但由于每次调用yield方法时,它都会放弃控制,直到再次调用它,这将一一生成斐波那契数,本质上代表所有斐波那契数的无限长列表。
还有另一种方法,
Fiber.yield
,具有类似的目的。 (事实上,我已经在上面描述过,因为Fiber
只是 Ruby 中协程的名称。)在Fiber
内部,您可以调用Fiber.yield
将控制权交还给最初将控制权交给您的执行上下文。最后,还有
yield
关键字,它在方法体内使用,以放弃对传递到方法中的块的控制。请注意,至少在
Enumerator
情况下(即第一个示例),您还可以将yield
解释为 生成,因为>Enumerator
每次调用yield
时都会生成一个新值。The word yield doesn't really have any special meaning in the context of Ruby. It means the same thing as it means in every other programming language, or in programming and computer science in general.
It is usually used when some kind of execution context surrenders control flow to a different execution context. For example, in Unix, there is a
sched_yield
function which a thread can use to give up the CPU to another thread (or process). With coroutines, the termyield
is generally used to transfer control from one coroutine to another. In C#, there is ayield
keyword, which is used by an iterator method to give up control to the iterating method.And in fact, this last usage is exactly identical to the usage of the
Enumerator::Yielder#yield
method in Ruby, which you were asking about. Calling this method will suspend the enumerator and give up control to the enumerating method.Example:
As you see, there is an infinite loop. Obviously, if this loop just ran on its own, it wouldn't be of much use. But since every time it hits the
yield
method, it gives up control until it is called again, this will produce the Fibonacci numbers one by one, essentially representing an infinitely long list of all Fibonacci numbers.There is another method,
Fiber.yield
, which serves a similar purpose. (In fact, I already described it above, becauseFiber
is just Ruby's name for coroutines.) Inside aFiber
, you callFiber.yield
to give up control back to the execution context that originally gave control to you.Lastly, there is the
yield
keyword, which is used inside a method body to give up control to the block that was passed into the method.Note that, at least in the
Enumerator
case (i.e. the first example), you can additionally interpretyield
as to produce, since theEnumerator
produces a new value, every time it callsyield
.在枚举器中的“yield”上下文中,其含义最接近“产生”。枚举器调用其yielder对象的yield方法,该方法“产生”传递给它的任何值。
结果是:
1
2
3
4
5
在屈服于区块的情况下,其含义最接近“投降”。带有yield 语句的方法会将执行交给您传递给该方法的任何块。
In the context of yielding in an Enumerator, the meaning is closest to "bring forth." The Enumerator calls the yield method of its yielder object, which "brings forth" any value passed to it.
This results in:
1
2
3
4
5
In the case of yielding to a block, the meaning is closest to "surrender." The method with the yield statement surrenders execution to whatever block you passed to that method.
您可能会发现阅读《Programming Ruby 1.9》中有关
yield
关键字的内容很有趣:更多阅读:
CLU 的历史 (pdf)
芭芭拉·利斯科夫(维基百科)
You may find it amusing to read what Programming Ruby 1.9 has to say about the
yield
keyword:More reading:
A History of CLU (pdf)
Barbara Liskov (wikipedia)
@Prostosuper,我最喜欢的相关定义是 这个:
在@Jamie Forrest的例子中,当调用wage_war时,“我应该做什么?”首先打印,然后流程控制被屈服(承认,放弃,授予,放弃)到调用wage_war的块,导致“投降!”正在打印。该块完成后,流程控制将在工资战争中恢复。如果yield之后还有其他语句,则当“投降!”之后在wage_war中恢复流程控制时,该语句将被执行。被打印了。
编辑:@Prostosuper询问yield,因为它与枚举器有关,而不是块,我的示例讨论了它在块中的使用。关于 Enumerator::Yielder#yield 的 SO 问题(含答案)位于此处。定义的含义仍然适用。
@Prostosuper, the related definition I like best is this one:
In @Jamie Forrest's example, when wage_war is called, "What should I do?" is printed first, then flow control is yielded (conceded, ceded, granted, given over) to the block that wage_war was called with, resulting in "Surrender!" being printed. After that block is complete, flow control resumes in wage_war. If there were another statement after the yield, it would be executed when flow control resumed in wage_war after "Surrender!" was printed.
EDIT: @Prostosuper asked about yield as it pertains to Enumerators, not blocks, and my example discusses its use in blocks. A SO question (with answers) about Enumerator::Yielder#yield is here. The sense of the definition still applies.
yield,在 ruby 上下文中“带来”:) 该块作为参数传递给您的方法。
打印
代码 p "hello world" 当 my_method 达到产量时执行
yield, in the ruby context "brings" :) the block passed as a parameter to your method.
prints
the code p "hello world" is executed when my_method reaches the yield
在 C# 循环中的yield 类似于 return 关键字,并且是迭代列表的循环的一部分。那为什么不使用 return 呢?因为使用yield,您可以在迭代该列表中的值时将控制权交还给循环。因此,yield 可能更像是一种控制机制。
In c# yield in a loop is something like a return keyword and is part of the loop that iterates the list. Why not using return then? Because with yield you give back control to the loop while iterating the values in that list. So may be yield is more like a control mechanism.