Project

General

Profile

Actions

Bug #18971

closed

Enumerator::Lazy.take(0) leaks first element into next operation

Added by Voileexperiments (Library Voile) 4 months ago. Updated 12 days ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
3.0.0p0 (2020-12-25 revision 95aff21468)
[ruby-core:109636]

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 # => []
Actions #1

Updated by Voileexperiments (Library Voile) 4 months ago

  • ruby -v changed from 3.0.0 to 3.0.0p0 (2020-12-25 revision 95aff21468)

Updated by Voileexperiments (Library Voile) 4 months 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) 4 months 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) 4 months ago

You're right. I just tested again and apparently even 3.1.2p20 has this issue.

Actions #5

Updated by Voileexperiments (Library Voile) 4 months ago

  • Description updated (diff)
Actions #6

Updated by Voileexperiments (Library Voile) 4 months ago

  • Description updated (diff)

Updated by nobu (Nobuyoshi Nakada) 3 months ago

Although not so elegant, I was thinking to add "precheck" to enumerators.
https://github.com/nobu/ruby/tree/lazy_take0

Actions #8

Updated by nobu (Nobuyoshi Nakada) 12 days ago

  • Status changed from Open to Closed

Applied in changeset git|ffc6c5d056e0f18a9bdfb9b1477d0192a6d37ea3.


[Bug #18971] Add precheck to enumerator

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0