From: "shugo (Shugo Maeda)" Date: 2013-01-22T10:24:10+09:00 Subject: [ruby-core:51555] [ruby-trunk - Bug #7696] Lazy enumerators with state can't be rewound Issue #7696 has been updated by shugo (Shugo Maeda). Assignee set to matz (Yukihiro Matsumoto) marcandre (Marc-Andre Lafortune) wrote: > shugo (Shugo Maeda) wrote: > > So, the following behavior is intended, right? > > > > $ ruby1.9.3 -I ~/src/backports/lib -r backports -r backports/2.0.0/enumerable -e "a = (1..3).lazy.zip(('a'..'z').each); p a.to_a; p a.to_a" > > [[1, "a"], [2, "b"], [3, "c"]] > > [[1, "d"], [2, "e"], [3, "f"]] > > That's a very good question. > > It probably would be best to call `to_enum` instead of `each`. Calling `next|rewind` on an enumerator should really only affect other calls to `next`. With `to_enum`, we'll get the same result every time. Even if to_enum is called, IO instances never be rewound, but I guess IO instances need not be rewound. > > It might be too late to introduce a new API for 2.0.0, so how about to move it to next minor? > > I understand. On the other hand, the API for Lazy.new was never decided upon and really should be finalized before 2.0.0! > > If we opt for the Yielder#memo way (and agree on the name), maybe we can convince mame to accept such a trivial change. In that case, the biggest "change" is the explicit guarantee of a different yielder per iteration. It's already the case (also for JRuby and rubinius), but AFAIK it's never been official. `The explicit guarantee of a different yielder per iteration' sounds acceptable for me, but I'm not sure whether Yielder#memo is a good name. > With the modified yielding way, it would be nice to include it in Lazy.new's api in this version, especially since it is still being finalized. > > At the very least, a note in the documentation about handling state would be needed for 2.0.0. I believe Matz should decide it. ---------------------------------------- Bug #7696: Lazy enumerators with state can't be rewound https://bugs.ruby-lang.org/issues/7696#change-35519 Author: marcandre (Marc-Andre Lafortune) Status: Open Priority: High Assignee: matz (Yukihiro Matsumoto) 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/