【发布时间】:2017-03-02 16:17:22
【问题描述】:
我在理解 Ruby 枚举器如何处理生成器块,尤其是无限序列的生成器时遇到了一点问题。我正在阅读 The Well Grounded Rubyist,有一个例子是这样的:
a = [1, 2, 3, 4, 5]
e = Enumerator.new do |y|
total = 0
until a.empty?
total += a.pop
y << total
end
end
e.take(2)
=> [5, 9]
a
=> [1, 2, 3]
我期望它做的是:它从头到尾迭代可枚举,然后返回结果集的前两个元素,将原始数组留空。但经过一番思考,我意识到这在生成器产生无限序列的情况下是行不通的——迭代永远不会结束。
现在,我知道当从外部可枚举创建时,Enumerator 使用 Fibers 来停止和恢复执行,每次底层 Enumerable 为每个块产生价值(或类似的东西,我只知道一般想法)。但是,如果 Enumerator 是从构造函数和生成器块创建的,它是如何工作的呢?
我曾尝试对底层的本机代码进行一些挖掘,但很快就迷失了方向,因为我的 C 技能至少可以说是低于标准的。根据我内部的理解,each 正在枚举器本身上被调用,take_i 函数作为一个块提供。但我找不到任何有关纤维的参考资料,也无法深入挖掘。
【问题讨论】:
标签: ruby