3.3 KiB
Vendored
mruby-enumerator
The mruby-enumerator mrbgem provides the Enumerator class, which allows for both internal and external iteration in mruby.
Purpose and Functionality
Enumerators are useful when you want to work with collections of data in a flexible way. They allow you to:
- Iterate externally: Fetch elements one by one using methods like
next. - Chain operations: Combine multiple iteration steps (e.g., mapping and then selecting) without creating intermediate arrays.
- Create custom iterators: Define your own iteration logic.
Creating an Enumerator
You can create an Enumerator in several ways:
-
Using
Kernel#to_enumorKernel#enum_for: This is the most common way. You can turn any object that has aneachmethod (or a similar iteration method) into an Enumerator.e = [1, 2, 3].to_enum # Creates an enumerator for the array e = "hello".enum_for(:each_byte) # Creates an enumerator for iterating over bytes -
Using
Enumerator.new: You can create an Enumerator by providing a block that defines how values are yielded.fib = Enumerator.new do |yielder| a = b = 1 loop do yielder << a a, b = b, a + b end end fib.take(5) # => [1, 1, 2, 3, 5]
Key Methods
The Enumerator class includes many helpful methods from the Enumerable module, as well as some of its own:
-
next: Returns the next value from the enumerator. RaisesStopIterationif the enumerator is at the end. -
peek: Returns the next value without advancing the iterator. -
rewind: Resets the enumerator to its beginning. -
with_index(offset = 0): Iterates over elements, providing both the element and its index (with an optional offset). Returns a new Enumerator if no block is given.["a", "b"].each.with_index(1) do |char, index| puts "#{index}: #{char}" end # Output: # 1: a # 2: b -
each_with_index: Similar towith_index(0). -
with_object(obj): Iterates over elements, passing an arbitrary object along with each element. Returns the given object. Returns a new Enumerator if no block is given.(1..3).each.with_object([]) do |i, arr| arr << i * 2 end # => [2, 4, 6] -
each(*args): Iterates over the enumerator. If arguments are provided, they are passed to the underlying iteration method. -
feed(value): Sets a value to be returned by theyieldinside the enumerator on its next call.
Chaining Enumerators
One of the powerful features of Enumerators is the ability to chain operations:
data = [1, 2, 3, 4, 5]
result = data.to_enum
.with_index # [[1, 0], [2, 1], [3, 2], [4, 3], [5, 4]]
.select { |num, idx| num.even? } # [[2, 1], [4, 3]]
.map { |num, idx| "#{idx}:#{num}" } # ["1:2", "3:4"]
p result # => ["1:2", "3:4"]
This avoids creating intermediate arrays for each step, making the code more efficient and readable for complex data transformations.
Integration
This mrbgem integrates the Enumerator class into mruby, making it available for use in your mruby projects. It also extends Kernel with to_enum and enum_for, and Enumerable with methods like zip, chunk, and chunk_while that leverage Enumerator.
Refer to the source code and tests for more detailed examples and advanced usage.