-
Notifications
You must be signed in to change notification settings - Fork 263
JEP Collections
In SDK we face several different collection types that we need
to iterate
, filter
, map
and reduce
. There is well established
convention for doing this operations on JS arrays that can be
employed to use consistent API across other types we deal with.
- Many XPCOM APIs return instances of nsISimpleEnumerator
- Some code uses Mozilla specific, non standard iterators & generators
- JS
Array
's - JS objects used as hash maps.
- Some APIs represent collections of items as objects that can be
iterated via
for
butobject[key]
is not avalue
mapped to akey
.
There several possible solutions to address this:
One solution would be wrap all non Array
types values into
an object providing implementations of Array
methods by
preserving semantics of the wrappee (iterators should stay
lazy, enumerators should open on consumption):
var result = enumerable(enumerator).
filter(predicate).
map(f).
reduce(accumulate);
var result = pairs(object).
filter(predicate).
map(f).
reduce(accumulate);
This solution has some inherent constraints:
- No way to interrupt iteration.
- We will need wrapper per type.
- Use of methods is insecure as they may be tempered.
underscore like API
Underscore is one of the most popular JS libraries and most used library on the server side JS. This is may be a good opportunity to employ popular API to solve our problem:
let { map, filter, reduce, chain } = require('sdk/collection')
var result = reduce(map(filter(enumerator, predicate), f), accumulate);
// Or use `chain`
var value = chain(enumerator).
filter(predicate).
map(f).
reduce(accumulate);
Note that these let's us solve some of the inherent problems
with a first option. For example underscore provides function
find that lets one stop an
iteration on first match. Also we could implement take
or
similar to generalize it further. Also we could use
Array.prototype
methods on arrays to guard against tempered
ones.