gpt4 book ai didi

ruby - 枚举器如何在 Ruby 1.9.1 中工作?

转载 作者:数据小太阳 更新时间:2023-10-29 06:52:01 25 4
gpt4 key购买 nike

这个问题不是关于如何在 Ruby 1.9.1 中使用枚举器,而是我很好奇它们是如何工作的。这是一些代码:

class Bunk
def initialize
@h = [*1..100]
end

def each
if !block_given?
enum_for(:each)
else
0.upto(@h.length) { |i|
yield @h[i]
}
end
end
end

在上面的代码中我可以使用e = Bunk.new.each,然后是e.nexte.next得到每个连续的元素,但它究竟是如何暂停执行然后在正确的位置恢复的?

我知道如果将 0.upto 中的 yield 替换为 Fiber.yield 则很容易理解,但此处并非如此。这是一个普通的旧 yield,那么它是如何工作的呢?

我查看了 enumerator.c,但它对我来说有点难以理解。也许有人可以使用纤程而不是 1.8.6 样式的基于延续的枚举器在 Ruby 中提供一个实现,这一切都清楚了吗?

最佳答案

这是一个使用纤程的普通 ruby​​ 枚举器,其行为应该与原始枚举器非常相似:

class MyEnumerator
include Enumerable

def initialize(obj, iterator_method)
@f = Fiber.new do
obj.send(iterator_method) do |*args|
Fiber.yield(*args)
end
raise StopIteration
end
end

def next
@f.resume
end

def each
loop do
yield self.next
end
rescue StopIteration
self
end
end

如果有人对使用异常控制流感到不安:真正的 Enumerator 最后也会引发 StopIteration,所以我只是模拟了原始行为。

用法:

>> enum = MyEnumerator.new([1,2,3,4], :each_with_index)
=> #<MyEnumerator:0x9d184f0 @f=#<Fiber:0x9d184dc>
>> enum.next
=> [1, 0]
>> enum.next
=> [2, 1]
>> enum.to_a
=> [[3, 2], [4, 3]]

关于ruby - 枚举器如何在 Ruby 1.9.1 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1436037/

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