Issue #6142 has been updated by Shugo Maeda.

File lazy_zip_to_a.diff added

Innokenty Mikhailov wrote:
>   a = (1..3).lazy.zip('a'..'z')
>   a.to_a #=> [[1, "a"], [2, "b"], [3, "c"]]
>   a.to_a #=> [[1, "d"], [2, "e"], [3, "f"]]
> 
> I believe that is not the desired behavior here and a.to_a should always return the same value.

I agree that the current behavior is confusing, and the attached patch fixes it in the above case, but the patch cannot fix it in the following case:

  a = (1..3).lazy.zip('a'..'z').map {|i| i.join(":")}
  p a.to_a #=> ["1:a", "2:b", "3:c"]
  p a.to_a #=> ["1:d", "2:e", "3:f"]

It may be difficult to fix it without performance decrease.
We have three options:

(1) Keep the current behavior.
(2) Rewind enumerators only when to_a is directly invoked on the lazy enumerator returned by lazy.zip.
(3) Rewind enumerators even if to_a is invoked on a chained enumerator.  This may cause performance decrease.

----------------------------------------
Bug #6142: Enumerable::Lazy#zip doesn't rewind internal enumerators
https://bugs.ruby-lang.org/issues/6142#change-24623

Author: Innokenty Mikhailov
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: ruby 2.0.0dev (2012-03-14 trunk 35013) [x86_64-linux]


All enumerables passed to Enumerable::Lazy#zip are converted into lazy enumerators.
When result evaluated - ruby iterates over this enumerators while calling #next to retrieve the next value.
But those enumerators are not rewinded:

  a = (1..3).lazy.zip('a'..'z')
  a.to_a #=> [[1, "a"], [2, "b"], [3, "c"]]
  a.to_a #=> [[1, "d"], [2, "e"], [3, "f"]]

I believe that is not the desired behavior here and a.to_a should always return the same value.


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