Enumerators
| External iteration | |
| Lazy chains | |
| each_with_object | |
| A Fibonacci enumerator |
External iteration
Calling each without a block returns an Enumerator, which is an iterator you drive by hand.
Each next call returns the following element, which helps when input arrives in steps.
enum = [1, 2, 3].each
puts enum.next
puts enum.next
ruby enum_demo.rb
1
2
Lazy chains
Long or endless sequences need lazy chains, so values are computed only on demand.
The lazy call turns the endless range into a lazy enumerator, and first pulls just five doubled values.
result = (1..).lazy.map { |n| n * 2 }.first(5)
p result
ruby lazy_demo.rb
[2, 4, 6, 8, 10]
each_with_object
The each_with_object method folds a collection into a memo object that the block mutates.
A hash with default zero counts letters without any key checks.
counts = ["a", "b", "a"].each_with_object(Hash.new(0)) do |letter, memo|
memo[letter] += 1
end
p counts
ruby counts_demo.rb
{"a"=>2, "b"=>1}
A Fibonacci enumerator
Custom sequences come from Enumerator.new with a block that yields each value.
An endless loop is safe here because first stops the sequence after six numbers.
fib = Enumerator.new do |y|
a = 0
b = 1
loop do
y << a
a, b = b, a + b
end
end
puts fib.first(6).inspect
ruby fib_demo.rb
[0, 1, 1, 2, 3, 5]
Next: Pattern matching
Article author: Arthur Isaev