Project

General

Profile

Feature #21520

Updated by nuzair46 (Nuzair Rasheed) 3 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 would be glad to work on this and make a PR. Thank you. 

Back