From: akr@... Date: 2014-05-11T08:55:16+00:00 Subject: [ruby-core:62522] [ruby-trunk - Feature #8840] Yielder#state Issue #8840 has been updated by Akira Tanaka. I have another idea now. How about combining Enumerator.new and Enumerator#lazy addition to closure? ``` class Enumerator::Lazy def drop4(n) Enumerator.new {|y| remain = n self.each {|v| if remain == 0 y.yield v else remain -= 1 end } }.lazy end end e = (1..42).lazy.drop4(40) # e is an Enumerator::Lazy object p e #=> #:each>> # e.map(&:odd?) returns an Enumerator::Lazy object p e.map(&:odd?) #=> #:each>>:map> # first e.to_a works p e.to_a #=> [41, 42] # second e.to_a works p e.to_a #=> [41, 42] # e.next and e.rewind works p e.next #=> 41 p e.next #=> 42 e.rewind p e.next #=> 41 p e.next #=> 42 ``` ---------------------------------------- Feature #8840: Yielder#state https://bugs.ruby-lang.org/issues/8840#change-46680 * Author: Marc-Andre Lafortune * Status: Feedback * Priority: Normal * Assignee: Yukihiro Matsumoto * Category: core * Target version: current: 2.2.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. ---Files-------------------------------- state.pdf (87.8 KB) -- https://bugs.ruby-lang.org/