Feature #708
Updated by sawa (Tsuyoshi Sawada) over 4 years ago
=begin There are a number of methods in `Enumerable` that Enumerable which build an `Array` Array of results from the entire collection: `map`, `select`, `take`, collection - e.g. map, select, take etc. I propose that the `Enumerator` Enumerator class have its own implementations of these methods, which return another `Enumerator`. Enumerator. Enumerators can then be chained: ```ruby seq.to_enum.map { ... }.select { ... }.take(...).each { |x| puts x } ``` This runs horizontally, "horizontally": that is, each element is processed left to right. No intermediate arrays are created, and it works happily with sequences of arbitrary length. infinite sequences. There are precendents for `SomeClass#select` SomeClass#select behaving differently to `Enumerable#select`. Enumerable#select. For example, `Hash#select` Hash#select now returns a `Hash`. Hash. So I believe it would be reasonable for `Enumerator` Enumerator to return another `Enumerator`. Enumerator. You can then choose between array-building or lazy evaluation, depending on whether there is an Enumerator in the chain. Of course, the last Enumerator has to be turned into something useful, e.g. by calling `to_a` to_a or `each each { ... }`. }. # Normal ```ruby res = (1..1_000_000).map { |x| x * 2 }.take(100) ``` # Lazy ```ruby res = (1..1_000_000).to_enum.map { |x| x * 2 }.take(100).to_a ``` I have attached a simple implementation of this for `select`, `map`, `take` select, map, take and a new method `skip`. skip. There are further methods like `take_while`, `zip` take_while, zip and so on which would also need to be implemented. =end