Feature #21520
Updated by nuzair46 (Nuzair Rasheed) 5 days ago
# Abstract Add a #peek method to Enumerator::Lazy that allows observing each element in a lazy enumeration pipeline without modifying or consuming the stream. # Background Ruby provides Enumerator::Lazy for efficient lazy stream processing. However, unlike languages such as Java, it lacks a clean way to inspect intermediate elements during lazy evaluation. Currently, developers must misuse .map for side effects, example: ```rb (1..).lazy.map { |x| puts x; x }.select(&:even?).first(3) ``` This is semantically incorrect and confusing, since .map implies transformation, not observation. # Proposal Introduce Enumerator::Lazy#peek, which yields each item to a block and returns the item unmodified, similar to Object#tap, but in a lazy stream: ```rb (1..).lazy .peek { |x| puts "saw: #{x}" } .select(&:even?) .first(3) ``` This would be equivalent to: ```rb lazy.map { |x| block.call(x); x } ``` but with improved semantic clarity. # Use cases • Debugging lazy enumerators without breaking the chain • Logging or instrumentation in pipelines • Educational / demo use for showing lazy evaluation step-by-step • Cleaner replacement for map { puts x; x } hacks Example: ```rb data = (1..).lazy .peek { |x| puts "got #{x}" } .select(&:even?) .first(5) ``` result: ```rb got 1 got 2 got 3 got 4 got 5 ... got 10 ``` And return [2, 4, 6, 8, 10] # Discussion #peek is a minimal, non-breaking addition that improves clarity and idiomatic usage of Enumerator::Lazy. It avoids abusing .map for observation and is familiar to developers from other languages. #peek is also not needed for other enumerators where .tap or .each can do the job. It mirrors Java’s .stream().peek(...) and makes Ruby’s lazy enumeration more expressive and readable. # See also • [Java Stream.peek](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#peek-java.util.function.Consumer-) I have would be glad to work on this and make a draft PR for the implementation ready https://github.com/ruby/ruby/pull/14024 PR. Thank you.