Bug #18971
closedEnumerator::Lazy.take(0) leaks first element into next operation
Description
These results with lazy enumerators are as expected:
(2..10).take(0).to_a # => []
(2..10).take(0).map(:&itself).to_a # => []
(2..10).lazy.take(0).to_a # => []
However, once another operation is added after take(0)
, if first element will pass through directly it will leak through:
(2..10).lazy.take(0).map(&:itself).to_a # => [2]
(2..10).lazy.take(0).select(&:even?).to_a # => [2]
(2..10).lazy.take(0).select(&:odd?).to_a # => []
(2..10).lazy.take(0).reject(&:even?).to_a # => []
(2..10).lazy.take(0).reject(&:odd?).to_a # => [2]
(2..10).lazy.take(0).take(1).to_a # => [2]
(2..10).lazy.take(0).take(0).take(1).to_a # => [2]
(2..10).lazy.take(0).drop(0).to_a # => [2]
(2..10).lazy.take(0).find_all {|_| true}.to_a # => [2]
(2..10).lazy.take(0).zip((12..20)).to_a # => [[2, 12]]
(2..10).lazy.take(0).uniq.to_a # => [2]
(2..10).lazy.take(0).sort.to_a # => []
(2..2).lazy.take(0).sort.to_a # => []
Non lazy versions all return []
as expected.
In 3.1.0 All of them behave as expected as well:
(2..10).lazy.take(0).map(&:itself).to_a # => []
(2..10).lazy.take(0).select(&:even?).to_a # => []
(2..10).lazy.take(0).select(&:odd?).to_a # => []
(2..10).lazy.take(0).reject(&:even?).to_a # => []
(2..10).lazy.take(0).reject(&:odd?).to_a # => []
(2..10).lazy.take(0).take(1).to_a # => []
(2..10).lazy.take(0).take(0).take(1).to_a # => []
(2..10).lazy.take(0).drop(0).to_a # => []
(2..10).lazy.take(0).find_all {|_| true}.to_a # => []
(2..10).lazy.take(0).zip((12..20)).to_a # => []
(2..10).lazy.take(0).uniq.to_a # => []
(2..10).lazy.take(0).sort.to_a # => []
(2..2).lazy.take(0).sort.to_a # => []
Updated by Voileexperiments (Library Voile) over 2 years ago
- ruby -v changed from 3.0.0 to 3.0.0p0 (2020-12-25 revision 95aff21468)
Updated by Voileexperiments (Library Voile) over 2 years ago
- Description updated (diff)
Upon more testing apparently this has been fixed in 3.0.2p107 (2021-07-07 revision 0db68f0233)
.
However I can't find a commit between p0 and p107 related to this change.
Updated by jeremyevans0 (Jeremy Evans) over 2 years ago
Are you sure this has been fixed? I tried with Ruby 2.7-3.1 and current master and did not get all []
results on any Ruby version I tested.
There is specific code to deal with an argument of 0, though I don't understand what it does. It comes from commit 29f73009ca934cfa7b51d1de4d22933ab56dc602 .
One way I found to work around this is to use an intermediate cycle(0)
enumerator. I submitted a pull request for that (https://github.com/ruby/ruby/pull/6273), though I expect @nobu (Nobuyoshi Nakada) could come up with a more elegant solution.
Updated by Voileexperiments (Library Voile) over 2 years ago
You're right. I just tested again and apparently even 3.1.2p20 has this issue.
Updated by Voileexperiments (Library Voile) over 2 years ago
- Description updated (diff)
Updated by Voileexperiments (Library Voile) over 2 years ago
- Description updated (diff)
Updated by nobu (Nobuyoshi Nakada) over 2 years ago
Although not so elegant, I was thinking to add "precheck" to enumerators.
https://github.com/nobu/ruby/tree/lazy_take0
Updated by nobu (Nobuyoshi Nakada) about 2 years ago
- Status changed from Open to Closed
Applied in changeset git|ffc6c5d056e0f18a9bdfb9b1477d0192a6d37ea3.
[Bug #18971] Add precheck to enumerator