ArrayLikeSequence
An ArrayLikeSequence
is a Sequence that provides random access to its elements. This extends the API for iterating with the additional methods #get and #length, allowing a sequence to act as a "view" into a collection or other indexed data source.
The initial sequence created by wrapping an array with Lazy(array)
is an ArrayLikeSequence
.
All methods of ArrayLikeSequence
that conceptually should return something like a array (with indexed access) return another ArrayLikeSequence
, for example:
- Sequence#map
- ArrayLikeSequence#slice
- Sequence#take and Sequence#drop
- Sequence#reverse
The above is not an exhaustive list. There are also certain other cases where it might be possible to return an ArrayLikeSequence
(e.g., calling Sequence#concat with a single array argument), but this is not guaranteed by the API.
Note that in many cases, it is not possible to provide indexed access without first performing at least a partial iteration of the underlying sequence. In these cases an ArrayLikeSequence
will not be returned:
- Sequence#filter
- Sequence#uniq
- Sequence#union
- Sequence#intersect
etc. The above methods only return ordinary Sequence objects.
Defining custom array-like sequences
Creating a custom ArrayLikeSequence
is essentially the same as creating a custom Sequence. You just have a couple more methods you need to implement: get
and (optionally) length
.
Here's an example. Let's define a sequence type called OffsetSequence
that offsets each of its parent's elements by a set distance, and circles back to the beginning after reaching the end. Remember: the initialization function you pass to #define should always accept a parent
as its first parameter.
ArrayLikeSequence.define("offset", {
init: function(parent, offset) {
this.offset = offset;
},
get: function(i) {
return this.parent.get((i + this.offset) % this.parent.length());
}
});
It's worth noting a couple of things here.
First, Lazy's default implementation of length
simply returns the parent's length. In this case, since an OffsetSequence
will always have the same number of elements as its parent, that implementation is fine; so we don't need to override it.
Second, the default implementation of each
uses get
and length
to essentially create a for
loop, which is fine here. If you want to implement each
your own way, you can do that; but in most cases (as here), you can probably just stick with the default.
So we're already done, after only implementing get
! Pretty easy, huh?
Now the offset
method will be chainable from any ArrayLikeSequence
. So for example:
Lazy([1, 2, 3]).map(mapFn).offset(3);
...will work, but:
Lazy([1, 2, 3]).filter(mapFn).offset(3);
...will not (because filter
does not return an ArrayLikeSequence
).
(Also, as with the example provided for defining custom Sequence types, this example really could have been implemented using a function already available as part of Lazy.js: in this case, Sequence#map.)
Examples
Lazy([1, 2, 3]) // instanceof Lazy.ArrayLikeSequence Lazy([1, 2, 3]).map(Lazy.identity) // instanceof Lazy.ArrayLikeSequence Lazy([1, 2, 3]).take(2) // instanceof Lazy.ArrayLikeSequence Lazy([1, 2, 3]).drop(2) // instanceof Lazy.ArrayLikeSequence Lazy([1, 2, 3]).reverse() // instanceof Lazy.ArrayLikeSequence Lazy([1, 2, 3]).slice(1, 2) // instanceof Lazy.ArrayLikeSequence