Project

General

Profile

Bug #10534

Enumerator methods other than "next" do not always respect "peek"

Added by jnicklas (Jonas Nicklas) about 5 years ago. Updated over 4 years ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]
[ruby-core:66389]

Description

It seems like using "peek" and then calling other methods on the Enumerator consumes the value that was peeked at. While next correctly returns the peeked-at value the next time it is called, other Enumerator methods such as to_a and each do not.

>> enum = StringIO.new("foo").each
=> #<Enumerator: #<StringIO:0x007ff3313d8688>:each>
>> enum.peek
=> "foo"
>> enum.to_a
=> []

Here the final call to enum.to_a should have returned ["foo"], since we have not consumed anything from the enumerator yet. The peeked-at value is not included in the returned Array.

Taking a glance at the code, it seems that these methods do not call next under the hood, but instead have some other mechanism of iterating over the Enumerator, this seems very counter-intuitive to me.

History

Updated by marcandre (Marc-Andre Lafortune) about 5 years ago

  • Assignee deleted (matz (Yukihiro Matsumoto))

next and peek indeed live in their little world described as "external enumeration" in the documentation.

The documentation of next and next_values states:

  • Note that +next_values+ does not affect other non-external enumeration
  • methods unless underlying iteration method itself has side-effect, e.g.
  • IO#each_line.

The doc of peek and peek_values would benefit from a similar note. Maybe we should turn it around in this case, like:

  • Note that +peek+ will affect other non-external enumeration
  • methods if underlying iteration method itself has side-effect, e.g.
  • IO#each_line.

Updated by bmesuere (Bart Mesuere) over 4 years ago

  • Subject changed from Enumerator methods other than "next" do not respect "peek" to Enumerator methods other than "next" do not always respect "peek"

I don't agree that a documentation would fix this. This issue results in unpredictable behaviour:

$ ruby -e "e=['a','b','c'].each;puts e.peek;puts e.next"
a
a
$ ruby -e "e=['a','b','c'].each;puts e.peek;e.each{|l| puts l}"
a
a
b
c
$ echo -e "a\nb\nc" | ruby -e "e=STDIN.each_line;puts e.peek;puts e.next"
a
a
$ echo -e "a\nb\nc" | ruby -e "e=STDIN.each_line;puts e.peek;e.each{|l| puts l}"
a
b
c

There's no way to know if the underlying iteration method has "side effects" except from trying it.

Also available in: Atom PDF