Sequence
The Sequence
object provides a unified API encapsulating the notion of zero or more consecutive elements in a collection, stream, etc.
Lazy evaluation
Generally speaking, creating a sequence should not be an expensive operation, and should not iterate over an underlying source or trigger any side effects. This means that chaining together methods that return sequences incurs only the cost of creating the Sequence
objects themselves and not the cost of iterating an underlying data source multiple times.
The following code, for example, creates 4 sequences and does nothing with source
:
var seq = Lazy(source) // 1st sequence
.map(func) // 2nd
.filter(pred) // 3rd
.reverse(); // 4th
Lazy's convention is to hold off on iterating or otherwise doing anything (aside from creating Sequence
objects) until you call each
:
seq.each(function(x) { console.log(x); });
Defining custom sequences
Defining your own type of sequence is relatively simple:
- Pass a method name and an object containing function overrides to Sequence.define. If the object includes a function called
init
, this function will be called upon initialization. - The object should include at least either a
getIterator
method or aneach
method. The former supports both asynchronous and synchronous iteration, but is slightly more cumbersome to implement. The latter supports synchronous iteration and can be automatically implemented in terms of the former. You can also implement both if you want, e.g. to optimize performance. For more info, see Iterator and AsyncSequence.
As a trivial example, the following code defines a new method, sample
, which randomly may or may not include each element from its parent.
Lazy.Sequence.define("sample", {
each: function(fn) {
return this.parent.each(function(e) {
// 50/50 chance of including this element.
if (Math.random() > 0.5) {
return fn(e);
}
});
}
});
(Of course, the above could also easily have been implemented using #filter instead of creating a custom sequence. But I did say this was a trivial example, to be fair.)
Now it will be possible to create this type of sequence from any parent sequence by calling the method name you specified. In other words, you can now do this:
Lazy(arr).sample();
Lazy(arr).map(func).sample();
Lazy(arr).map(func).filter(pred).sample();
Etc., etc.