Project

General

Profile

Actions

Feature #708

closed

Lazy Enumerator#select, Enumerator#map etc.

Added by candlerb (Brian Candler) over 13 years ago. Updated about 2 years ago.

Status:
Rejected
Priority:
Normal
Target version:
[ruby-core:19680]

Description

There are a number of methods in Enumerable that build an Array of results from the entire collection: map, select, take, etc.

I propose that the Enumerator class have its own implementations of these methods, which return another Enumerator. Enumerators can then be chained:

seq.to_enum.map { ... }.select { ... }.take(...).each { |x| puts x }

This runs horizontally, that is, each element is processed left to right. No intermediate arrays are created, and it works happily with sequences of arbitrary length.

There are precendents for SomeClass#select behaving differently to Enumerable#select. For example, Hash#select returns a Hash. So I believe it would be reasonable for Enumerator to return another 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 or each { ... }.

Normal

res = (1..1_000_000).map { |x| x * 2 }.take(100)

Lazy

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 and a new method skip. There are further methods like take_while, zip and so on which would also need to be implemented.


Files

lazy_enum.rb (1.75 KB) lazy_enum.rb candlerb (Brian Candler), 11/03/2008 06:54 PM

Related issues 2 (0 open2 closed)

Related to Ruby master - Feature #4653: [PATCH 1/1] new method Enumerable#rude_mapRejectedmatz (Yukihiro Matsumoto)05/08/2011Actions
Related to Ruby master - Feature #4890: Enumerable#lazyClosedyhara (Yutaka HARA)06/16/2011Actions
Actions

Also available in: Atom PDF