From: "marcandre (Marc-Andre Lafortune)" Date: 2013-10-03T00:10:48+09:00 Subject: [ruby-core:57603] [ruby-trunk - Feature #8840] Yielder#state Issue #8840 has been updated by marcandre (Marc-Andre Lafortune). akr (Akira Tanaka) wrote: > Would��you��explain��the��incompleteness��concretely? Sure. With your code above: e.drop2(40).map(&:odd?) # => [true, false] # expected lazy enumerator, as with original drop: e.drop(40).map(&:odd?) # => #:drop(40)>:map> Here is another implementation using `with_state` that returns a lazy enumerator: class Enumerator::Lazy def drop3(n) Lazy.new(with_state(remain: n)) do |y, (state, v)| if state[:remain] == 0 y.yield v else state[:remain] -= 1 end end end end This implementation doesn't look so bad. It's probably quite a bit slower than using a Yielder#state method though. ---------------------------------------- Feature #8840: Yielder#state https://bugs.ruby-lang.org/issues/8840#change-42216 Author: marcandre (Marc-Andre Lafortune) Status: Feedback Priority: Normal Assignee: matz (Yukihiro Matsumoto) Category: core Target version: current: 2.1.0 Defining an Enumerator that require a state is currently troublesome. For example, it is not really possible to define an equivalent of Lazy#drop in Ruby without making an assumption on the implementation. To address this, I propose that we (a) guarantee that a new Yielder object will be given for each enumeration (b) add a 'state' attribute to Yielder. This way, one could implement Lazy#drop in a way similar to: class Enumerator::Lazy < Enumerator def drop(n) n = n.to_i Lazy.new(self) do |yielder, *values| yielder.state ||= n if yielder.state > 0 yielder.state -= 1 else yielder.yield(*values) end end end end Note that (a) is currently true for Ruby MRI, JRuby and Rubinius, but it is not explicit in the documentation. -- http://bugs.ruby-lang.org/