[#51213] [ruby-trunk - Bug #7645][Open] BigDecimal#== slow when compared to true/false — "mathie (Graeme Mathieson)" <mathie@...>

11 messages 2013/01/01

[#51328] [ruby-trunk - Bug #7676][Open] Comparison of Float::NAN in array behaves unexpectedly — "simonrussell (Simon Russell)" <spam+ruby@...>

11 messages 2013/01/09

[#51347] [ruby-trunk - Bug #7679][Open] IRB history is broken — "zzak (Zachary Scott)" <zachary@...>

15 messages 2013/01/10

[#51389] [ruby-trunk - Bug #7688][Open] Error hiding with rb_rescue() on Comparable#==, #coerce and others — "Eregon (Benoit Daloze)" <redmine@...>

34 messages 2013/01/11

[#51430] [ruby-trunk - Bug #7696][Open] Lazy enumerators with state can't be rewound — "marcandre (Marc-Andre Lafortune)" <ruby-core@...>

15 messages 2013/01/14

[#51437] [ruby-trunk - Bug #7698][Open] RubyGems 2.0 has an incompatibility about installation of extension libraries — "mrkn (Kenta Murata)" <muraken@...>

21 messages 2013/01/15

[#51454] [CommonRuby - Feature #7701][Open] Non-optional (required) keyword args — "headius (Charles Nutter)" <headius@...>

31 messages 2013/01/15

[#51499] [ruby-trunk - Feature #7712][Open] Add .txt extensions to all plain-text documentation files for Windows users — "postmodern (Hal Brodigan)" <postmodern.mod3@...>

9 messages 2013/01/18

[#51619] [ruby-trunk - Feature #7738][Open] Deprecate Set#+ as an alias of Set#|, use it for symmetric difference. Introduce Hash#| for Hash#reverse_merge in Rails. — "alexeymuranov (Alexey Muranov)" <redmine@...>

11 messages 2013/01/24

[#51623] [ruby-trunk - Feature #7739][Open] Define Hash#| as Hash#reverse_merge in Rails — "alexeymuranov (Alexey Muranov)" <redmine@...>

24 messages 2013/01/24

[#51714] [CommonRuby - Feature #7747][Open] Expanded API for Binding semantics — "jballanc (Joshua Ballanco)" <jballanc@...>

19 messages 2013/01/27

[#51742] [ruby-trunk - Bug #7756][Open] clang 3.2 sees through UNINITIALIZED_VAR macro, gives warning — "drbrain (Eric Hodel)" <drbrain@...7.net>

10 messages 2013/01/29

[#51763] [ruby-trunk - Bug #7758][Open] Ruby on Windows crashes when active codepage is codepage 65001 and outputting unicode character — "joshc (Josh C)" <josh.nw@...>

16 messages 2013/01/30

[ruby-core:51521] [ruby-trunk - Bug #7696] Lazy enumerators with state can't be rewound

From: "marcandre (Marc-Andre Lafortune)" <ruby-core@...>
Date: 2013-01-19 17:33:16 UTC
List: ruby-core #51521
Issue #7696 has been updated by marcandre (Marc-Andre Lafortune).


The same idea will work for zip too; the arguments must be converted to enumerators only when yielder.memo is not set, i.e. every new yielder.

The arguments are never really rewound, but the first yielder holding them will not be reused after enum.rewind; a new yielder is given.
I haven't checked if that's the current behavior in other implementations, but if yielder is to be the state holder, that's the way it should work.

    enum = (1..2).lazy.zip(1..2)
    enum.next # => yielder.memo was nil, so (1..2).each is called and stored in the memo
    enum.rewind # => the original yielder is discarded
    enum.next # => the second yielder.memo is nil, so (1..2).each is called again and stored in the memo

I'm using the same idea in my `backports` gem to implement this in pure Ruby:

    https://github.com/marcandre/backports/blob/master/lib/backports/2.0.0/enumerator/lazy.rb

The only other possibility that would work is to pass yield extra 'state' argument when required, like:

  def drop(n)
      Lazy.new(self, state: ->{{remain: n}}) do |yielder, state, *values|
        if state[:remain] > 0
          state[:remain] -= 1
        else
          yielder.yield(*values)
        end
      end
    end  

Maybe the :state option could be an object instead of a lmabda, which would be dupped before each enumerations:

  def drop(n)
      Lazy.new(self, state: {remain: n}) do |yielder, state, *values|
        if state[:remain] > 0
          state[:remain] -= 1
        else
          yielder.yield(*values)
        end
      end
    end  

Both solutions seem complex to me, but would definitely put the correct emphasis on how to deal with state.


So, does the patch look acceptable as far as MRI is concerned?
For the public api, should there be a public Yielder#memo and a guarantee that there is exactly one yielder object per iteration? or instead an extra state yielded when required?

----------------------------------------
Bug #7696: Lazy enumerators with state can't be rewound
https://bugs.ruby-lang.org/issues/7696#change-35488

Author: marcandre (Marc-Andre Lafortune)
Status: Open
Priority: High
Assignee: 
Category: core
Target version: 2.0.0
ruby -v: r38800


The 4 lazy enumerators requiring internal state, i.e. {take|drop}{_while}, don't work as expected after a couple `next` and a call to `rewind`.

For example:

    e=(1..42).lazy.take(2)
    e.next # => 1
    e.next # => 2
    e.rewind
    e.next # => 1
    e.next # => StopIteration: iteration reached an end, expected 2

This is related to #7691; the current API does not give an easy way to handle state.

Either there's a dedicated callback to rewind, or data must be attached to the yielder.


-- 
http://bugs.ruby-lang.org/

In This Thread