
Issue #19294 has been updated by nevans (Nicholas Evans). Perhaps `#rewind` could be called, but (IMO) that shouldn't be the default either. Two kwargs? ```ruby Enumerator.product(*enums, rewind: boolish, memoize: boolish) {|elements| ... } ``` Or one? ```ruby Enumerator.product(rewind: (bool | :rewind | :memoize) {|elements| ... } ``` In the meantime, it should at least be documented, and that documentation should include simple workarounds such as: When the consumable enumerator doesn't take up too much memory: ```ruby Enumerator .product([1, 2, 3], s.each_char.to_a) .to_a # => # [[1, "a"], # [2, "a"], # [3, "a"], # [1, "b"], # [2, "b"], # [3, "b"], # [1, "c"], # [2, "c"], # [3, "c"]] ``` If rewinding works (`to_a` is just for the example. presumably you wouldn't use `to_a` if memory use is a motivator): ```ruby rewinder = Enumerator.new do |y| s.rewind s.each_char(&y) end Enumerator .product([1, 2, 3], rewinder) .to_a # => # [[1, "a"], # [2, "a"], # [3, "a"], # [1, "b"], # [2, "b"], # [3, "b"], # [1, "c"], # [2, "c"], # [3, "c"]] ``` If you only have a single consumable enumerator, it might not fit in memory and it can't or shouldn't rewind: ```ruby Enumerator .product(s.each_char, [1, 2, 3]) .lazy .map(&:reverse) .to_a # => # [[1, "a"], # [2, "a"], # [3, "a"], # [1, "b"], # [2, "b"], # [3, "b"], # [1, "c"], # [2, "c"], # [3, "c"]] ``` ---------------------------------------- Feature #19294: Enumerator.product works incorrectly with consuming enumerators https://bugs.ruby-lang.org/issues/19294#change-103065 * Author: zverok (Victor Shepelev) * Status: Open * Priority: Normal ---------------------------------------- ```ruby s = StringIO.new('abc') Enumerator.product([1, 2, 3], s.each_char).to_a # Expected: => [[1, "a"], [1, "b"], [1, "c"], [2, "a"], [2, "b"], [2, "c"], [3, "a"], [3, "b"], [3, "c"]] # Actual: => [[1, "a"], [1, "b"], [1, "c"]] ``` The implementation consumes the non-first enumerator to produce the first combination. Somewhat related to the dilemma of consuming and non-consuming enumerators (#19061). PS: I noticed I don't understand why it is `Enumerator.product` and not `Enumerable#product`, but probably it is too late to raise the questions :( -- https://bugs.ruby-lang.org/