目前我正在阅读David A. Black撰写的“The Well-Grounded Rubyist”,我坚持10.9章(枚举数和可枚举的下一个维度)。我的问题是关于yield
方法。
Ruby上下文中单词yield
的含义是什么?我的母语是俄语,谷歌翻译向我展示了一堆翻译变体,让我感到困惑。其中有一些:给,带来,投降(放弃),生产,同意,遵守和其他许多人。
UPD:请注意,我正在尝试理解Enumerator::Yielder#yield方法的含义,而不是yield
关键字本身。
UPD_2:我发现了有关枚举数的有趣文章:“Lazy Enumerators in Ruby”。
答案 0 :(得分:18)
单词 yield 在Ruby的上下文中并没有任何特殊含义。它与其他编程语言或编程和计算机科学中的含义完全相同。
通常在某种执行上下文放弃控制流向不同的执行上下文时使用。例如,在Unix中,有一个sched_yield
函数,线程可以使用该函数将CPU放弃到另一个线程(或进程)。使用协同程序,术语yield
通常用于将控制从一个协程转移到另一个协程。在C#中,有一个yield
关键字,迭代器方法使用它来放弃对迭代方法的控制。
事实上,最后一个用法与Ruby中Enumerator::Yielder#yield
方法的用法完全相同,您要问的是。调用此方法将暂停枚举器并放弃对枚举方法的控制。
示例:
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的coroutines名称。)在Fiber
内,你调用Fiber.yield
放弃对最初执行上下文的控制权控制了你。
最后,有yield
关键字,它在方法体内使用,以放弃对传递给方法的块的控制。
请注意,至少在Enumerator
案例(即第一个示例)中,您可以另外将yield
解释为以生成,因为Enumerator
每次调用yield
时都会生成一个新值。
答案 1 :(得分:3)
在枚举器中屈服的背景下,意义最接近于“带来”。 Enumerator调用其yielder对象的yield方法,该方法“带出”传递给它的任何值。
give_me = Enumerator.new do |yielder|
(1..5).each do |n|
yielder.yield n
end
end
5.times do
p give_me.next
end
这导致:
1
2
3
4
5个
在屈服于一个区块的情况下,意义最接近于“投降”。带有yield语句的方法将执行放弃到传递给该方法的任何块。
def wage_war
p "What should I do?"
yield
end
wage_war { p "Surrender!" }
答案 2 :(得分:2)
@Prostosuper,我最喜欢的相关定义是this one:
承认,放弃,给予(放弃; 放弃或放弃 物理控制另一个)
在@Jamie Forrest的例子中,当调用wage_war时,“我该怎么办?”首先打印,然后将流量控制产生(承认,割让,授予,给予)给pay_war被调用的块,导致“投降!”正在印刷。该块完成后,流量控制将在wage_war中恢复。如果在收益率之后还有另一个语句,那么在“投降”之后,当在wage_war中恢复流量控制时,它将被执行。印刷了。
编辑:@ Prostosuper询问与 枚举器 相关的产量,而不是块,我的示例讨论了它在块中的使用。关于Enumerator :: Yielder#yield的SO问题(有答案)是here。定义的意义仍然适用。
答案 3 :(得分:2)
您可能会发现阅读Programming Ruby 1.9对yield
关键字所说的内容很有趣:
编程语言增益很高兴知道选择关键字
yield
来回应收益率 在Liskov的语言CLU中运行,这种语言已有三十多年的历史,但仍包含一些功能 没有被CLU-less广泛利用。
更多阅读:
A History of CLU(pdf)
Barbara Liskov(维基百科)
答案 4 :(得分:0)
yield,在ruby上下文中“带来”:)作为参数传递给您的方法的块。
def my_method
p "I have to say something:"
yield
end
my_method do
p "hello world!"
end
打印
I have to say something:
hello world
代码p“hello world”在my_method达到yield
时执行答案 5 :(得分:0)
在c#中,循环中的yield类似于return关键字,并且是迭代列表的循环的一部分。那为什么不使用return呢?因为使用yield可以在迭代该列表中的值时将控制权交还给循环。因此产量可能更像是一种控制机制。