gpt4 book ai didi

ruby - 帮助理解 Ruby 中的产量和枚举器

转载 作者:数据小太阳 更新时间:2023-10-29 07:24:23 26 4
gpt4 key购买 nike

如果有人能帮助我理解在枚举器中使用 Yielder 与仅在枚举器中调用 yield 之间的区别,我将不胜感激。

“有根有据的 Ruby 主义者”表示,人们不会“从障碍中屈服”,但不会准确解释发生了什么。

谢谢

最佳答案

如果您首先了解 yield 的工作原理,可能会有所帮助。这是一个例子:

def do_stuff
if block_given?
yield 5
else
5
end
end

result = do_stuff {|x| x * 3 }
puts result

--output:--
15

在do_stuff方法中调用:

do_stuff {|x| x * 3 }

..这个 block 就像一个函数,它被传递给方法do_stuff。在 do_stuff 内部,yield 调用该函数并传递指定的参数——在本例中为 5。

一些重要的注意事项:

  1. yield 在方法中调用

  2. 当你调用一个方法时,你可以将一个 block 传递给该方法

  3. yield用于调用block。

好的,现在让我们看看您的评论问题:

Is it true that

e = Enumerator.new do |y| 
y << 1
y << 2
y << 3
end

is exactly the same as

e = Enumerator.new do   #I think you forgot to write .new here
yield 1
yield 2
yield 3
end

在第二个例子中,任何地方都没有方法定义——所以你不能调用 yield。错误!因此,这两个例子并不相同。

但是,您可以这样做:

def do_stuff
e = Enumerator.new do
yield 1
yield 2
yield 3
end
end

my_enum = do_stuff {|x| puts x*3}
my_enum.next

--output:--
3
6
9
1.rb:12:in `next': iteration reached an end (StopIteration)
from 1.rb:12:in `<main>'

但这是一个有趣的枚举器,因为它不产生任何值——它只是执行一些代码(恰好打印一些输出),然后结束。该枚举器几乎等同于:

def do_stuff
e = Enumerator.new do
end
end

my_enum = do_stuff
my_enum.next

--output:--
1.rb:7:in `next': iteration reached an end (StopIteration)
from 1.rb:7:in `<main>'

当枚举器无法生成值时,它会引发 StopIteration 异常。因此在这两种情况下,枚举器都无法产生值。

But it's still not clear to me what the "yielder" is doing. It looks like it is collecting all the calculated values so that it can regurgitate them later when you use the enumerator. If that's the case, then it seems like it would only be practical for "small" sequences....you wouldn't want to make an enumerator that stored 50 million items away.

没有。事实上,您可以创建一个枚举器来产生无限数量的值。这是一个例子:

e = Enumerator.new do |y|
val = 1

while true
y << val
val += 1
end

end

puts e.next
puts e.next
puts e.next

--output:--
1
2
3

添加一些调试消息应该证明是有见地的:

e = Enumerator.new do |y|
val = 1

while true
puts "in while loop"
y << val
val += 1
end

end

puts e.next

--output:--
in while loop
1

请注意,该消息只打印一次。所以发生了一些不明显的事情:

e = Enumerator.new do |y|
val = 1

while true
puts "in while loop"
y << val
puts "just executed y << val"
val += 1
end

end

puts e.next

--output:--
in while loop
1

因为消息“just executed y << val”没有出现在输出中,这意味着执行必须在 y << val 行停止.因此,枚举器不会连续旋转 while 循环并将所有值插入 y——即使语法与将值插入数组完全相同:arr << val .

什么 y << val真正的意思是:当调用 e.next() 时产生这个值,然后在下一行继续执行。如果您在前面的示例中添加另一个 e.next,您将看到这个额外的输出:

just executed y << val
in while loop
2

发生的事情是执行总是在 y << val 时停止。在代码中遇到。然后调用 e.next 产生右侧的值,然后在下一行继续执行。

如果 ruby​​ 将 yielder 语句的语法写成这样,可能会更有意义:

y >> val

我们可以将其解释为:在这里停止执行,然后在调用 e.next 时产生 val。

David Black 建议不要使用 y.yield val语法,相当于 y << val以免读者认为它的工作原理与 yield 语句类似。 y.yield val应该理解为:“这里停止执行,当next调用produce val时,再下一行继续执行。个人认为语法y << valy.yield val更突出,所以更容易发现在代码中并轻松识别执行停止的位置。

关于ruby - 帮助理解 Ruby 中的产量和枚举器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/993026/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com