我很惊讶Enumerator#each没有从序列中的当前位置开始。
o = Object.new
def o.each
yield 1
yield 2
yield 3
end
e = o.to_enum
puts e.next
puts e.next
e.each{|x| puts x}
# I expect to see 1,2,3 but I see 1,2,1,2,3
# apparently Enumerator's each (inherited from Enumerable) restarts the sequence!我做错了吗?有没有一种方法可以构造另一个枚举器(来自e),使其具有预期的每个行为?
发布于 2013-05-06 03:41:40
您没有做错,只是这不是为Enumerator#each定义的语义。您可以创建一个派生枚举器,它只从当前位置迭代到末尾:
class Enumerator
def enum_the_rest
Enumerator.new { |y| loop { y << self.next } }
end
end
o = Object.new
def o.each
yield 1
yield 2
yield 3
end
e = o.to_enum
=> #<Enumerator: ...>
e.next
=> 1
e2 = e.enum_the_rest
=> #<Enumerator: ...>
e2.each { |x| puts x }
=> 2
=> 3顺便说一句,each不会重新启动序列,它只是在整个范围内运行。您的枚举器仍然知道它相对于下一次next调用的位置。
e3 = o.to_enum
e3.next
=> 1
e3.next
=> 2
e3.map(&:to_s)
=> ["1", "2", "3"]
e3.next
=> 3发布于 2013-05-06 03:48:46
Enumerator#next和Enumerator#each在对象上的工作方式不同。根据#each的文档(重点是我的):
根据此枚举数的构造方式遍历块。如果未给出块,则返回self。
因此,#each的行为始终基于原始设置,而不是当前的内部状态。如果您在源代码方面很快达到顶峰,您将看到rb_obj_dup被调用来设置一个新的枚举器。
https://stackoverflow.com/questions/16387530
复制相似问题