summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/sdk/util/sequence.js
diff options
context:
space:
mode:
Diffstat (limited to 'addon-sdk/source/lib/sdk/util/sequence.js')
-rw-r--r--addon-sdk/source/lib/sdk/util/sequence.js593
1 files changed, 0 insertions, 593 deletions
diff --git a/addon-sdk/source/lib/sdk/util/sequence.js b/addon-sdk/source/lib/sdk/util/sequence.js
deleted file mode 100644
index 28e3de255..000000000
--- a/addon-sdk/source/lib/sdk/util/sequence.js
+++ /dev/null
@@ -1,593 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-module.metadata = {
- "stability": "experimental"
-};
-
-// Disclamer:
-// In this module we'll have some common argument / variable names
-// to hint their type or behavior.
-//
-// - `f` stands for "function" that is intended to be side effect
-// free.
-// - `p` stands for "predicate" that is function which returns logical
-// true or false and is intended to be side effect free.
-// - `x` / `y` single item of the sequence.
-// - `xs` / `ys` sequence of `x` / `y` items where `x` / `y` signifies
-// type of the items in sequence, so sequence is not of the same item.
-// - `_` used for argument(s) or variable(s) who's values are ignored.
-
-const { complement, flip, identity } = require("../lang/functional");
-const { isArray, isArguments, isMap, isSet, isGenerator,
- isString, isBoolean, isNumber } = require("../lang/type");
-
-const Sequence = function Sequence(iterator) {
- if (!isGenerator(iterator)) {
- throw TypeError("Expected generator argument");
- }
-
- this[Symbol.iterator] = iterator;
-};
-exports.Sequence = Sequence;
-
-const polymorphic = dispatch => x =>
- x === null ? dispatch.null(null) :
- x === void(0) ? dispatch.void(void(0)) :
- isArray(x) ? (dispatch.array || dispatch.indexed)(x) :
- isString(x) ? (dispatch.string || dispatch.indexed)(x) :
- isArguments(x) ? (dispatch.arguments || dispatch.indexed)(x) :
- isMap(x) ? dispatch.map(x) :
- isSet(x) ? dispatch.set(x) :
- isNumber(x) ? dispatch.number(x) :
- isBoolean(x) ? dispatch.boolean(x) :
- dispatch.default(x);
-
-const nogen = function*() {};
-const empty = () => new Sequence(nogen);
-exports.empty = empty;
-
-const seq = polymorphic({
- null: empty,
- void: empty,
- array: identity,
- string: identity,
- arguments: identity,
- map: identity,
- set: identity,
- default: x => x instanceof Sequence ? x : new Sequence(x)
-});
-exports.seq = seq;
-
-// Function to cast seq to string.
-const string = (...etc) => "".concat(...etc);
-exports.string = string;
-
-// Function for casting seq to plain object.
-const object = (...pairs) => {
- let result = {};
- for (let [key, value] of pairs)
- result[key] = value;
-
- return result;
-};
-exports.object = object;
-
-// Takes `getEnumerator` function that returns `nsISimpleEnumerator`
-// and creates lazy sequence of it's items. Note that function does
-// not take `nsISimpleEnumerator` itslef because that would allow
-// single iteration, which would not be consistent with rest of the
-// lazy sequences.
-const fromEnumerator = getEnumerator => seq(function* () {
- const enumerator = getEnumerator();
- while (enumerator.hasMoreElements())
- yield enumerator.getNext();
-});
-exports.fromEnumerator = fromEnumerator;
-
-// Takes `object` and returns lazy sequence of own `[key, value]`
-// pairs (does not include inherited and non enumerable keys).
-const pairs = polymorphic({
- null: empty,
- void: empty,
- map: identity,
- indexed: indexed => seq(function* () {
- const count = indexed.length;
- let index = 0;
- while (index < count) {
- yield [index, indexed[index]];
- index = index + 1;
- }
- }),
- default: object => seq(function* () {
- for (let key of Object.keys(object))
- yield [key, object[key]];
- })
-});
-exports.pairs = pairs;
-
-const names = polymorphic({
- null: empty,
- void: empty,
- default: object => seq(function*() {
- for (let name of Object.getOwnPropertyNames(object)) {
- yield name;
- }
- })
-});
-exports.names = names;
-
-const symbols = polymorphic({
- null: empty,
- void: empty,
- default: object => seq(function* () {
- for (let symbol of Object.getOwnPropertySymbols(object)) {
- yield symbol;
- }
- })
-});
-exports.symbols = symbols;
-
-const keys = polymorphic({
- null: empty,
- void: empty,
- indexed: indexed => seq(function* () {
- const count = indexed.length;
- let index = 0;
- while (index < count) {
- yield index;
- index = index + 1;
- }
- }),
- map: map => seq(function* () {
- for (let [key, _] of map)
- yield key;
- }),
- default: object => seq(function* () {
- for (let key of Object.keys(object))
- yield key;
- })
-});
-exports.keys = keys;
-
-
-const values = polymorphic({
- null: empty,
- void: empty,
- set: identity,
- indexed: indexed => seq(function* () {
- const count = indexed.length;
- let index = 0;
- while (index < count) {
- yield indexed[index];
- index = index + 1;
- }
- }),
- map: map => seq(function* () {
- for (let [_, value] of map) yield value;
- }),
- default: object => seq(function* () {
- for (let key of Object.keys(object)) yield object[key];
- })
-});
-exports.values = values;
-
-
-
-// Returns a lazy sequence of `x`, `f(x)`, `f(f(x))` etc.
-// `f` must be free of side-effects. Note that returned
-// sequence is infinite so it must be consumed partially.
-//
-// Implements clojure iterate:
-// http://clojuredocs.org/clojure_core/clojure.core/iterate
-const iterate = (f, x) => seq(function* () {
- let state = x;
- while (true) {
- yield state;
- state = f(state);
- }
-});
-exports.iterate = iterate;
-
-// Returns a lazy sequence of the items in sequence for which `p(item)`
-// returns `true`. `p` must be free of side-effects.
-//
-// Implements clojure filter:
-// http://clojuredocs.org/clojure_core/clojure.core/filter
-const filter = (p, sequence) => seq(function* () {
- if (sequence !== null && sequence !== void(0)) {
- for (let item of sequence) {
- if (p(item))
- yield item;
- }
- }
-});
-exports.filter = filter;
-
-// Returns a lazy sequence consisting of the result of applying `f` to the
-// set of first items of each sequence, followed by applying f to the set
-// of second items in each sequence, until any one of the sequences is
-// exhausted. Any remaining items in other sequences are ignored. Function
-// `f` should accept number-of-sequences arguments.
-//
-// Implements clojure map:
-// http://clojuredocs.org/clojure_core/clojure.core/map
-const map = (f, ...sequences) => seq(function* () {
- const count = sequences.length;
- // Optimize a single sequence case
- if (count === 1) {
- let [sequence] = sequences;
- if (sequence !== null && sequence !== void(0)) {
- for (let item of sequence)
- yield f(item);
- }
- }
- else {
- // define args array that will be recycled on each
- // step to aggregate arguments to be passed to `f`.
- let args = [];
- // define inputs to contain started generators.
- let inputs = [];
-
- let index = 0;
- while (index < count) {
- inputs[index] = sequences[index][Symbol.iterator]();
- index = index + 1;
- }
-
- // Run loop yielding of applying `f` to the set of
- // items at each step until one of the `inputs` is
- // exhausted.
- let done = false;
- while (!done) {
- let index = 0;
- let value = void(0);
- while (index < count && !done) {
- ({ done, value } = inputs[index].next());
-
- // If input is not exhausted yet store value in args.
- if (!done) {
- args[index] = value;
- index = index + 1;
- }
- }
-
- // If none of the inputs is exhasted yet, `args` contain items
- // from each input so we yield application of `f` over them.
- if (!done)
- yield f(...args);
- }
- }
-});
-exports.map = map;
-
-// Returns a lazy sequence of the intermediate values of the reduction (as
-// per reduce) of sequence by `f`, starting with `initial` value if provided.
-//
-// Implements clojure reductions:
-// http://clojuredocs.org/clojure_core/clojure.core/reductions
-const reductions = (...params) => {
- const count = params.length;
- let hasInitial = false;
- let f, initial, source;
- if (count === 2) {
- [f, source] = params;
- }
- else if (count === 3) {
- [f, initial, source] = params;
- hasInitial = true;
- }
- else {
- throw Error("Invoked with wrong number of arguments: " + count);
- }
-
- const sequence = seq(source);
-
- return seq(function* () {
- let started = hasInitial;
- let result = void(0);
-
- // If initial is present yield it.
- if (hasInitial)
- yield (result = initial);
-
- // For each item of the sequence accumulate new result.
- for (let item of sequence) {
- // If nothing has being yield yet set result to first
- // item and yield it.
- if (!started) {
- started = true;
- yield (result = item);
- }
- // Otherwise accumulate new result and yield it.
- else {
- yield (result = f(result, item));
- }
- }
-
- // If nothing has being yield yet it's empty sequence and no
- // `initial` was provided in which case we need to yield `f()`.
- if (!started)
- yield f();
- });
-};
-exports.reductions = reductions;
-
-// `f` should be a function of 2 arguments. If `initial` is not supplied,
-// returns the result of applying `f` to the first 2 items in sequence, then
-// applying `f` to that result and the 3rd item, etc. If sequence contains no
-// items, `f` must accept no arguments as well, and reduce returns the
-// result of calling f with no arguments. If sequence has only 1 item, it
-// is returned and `f` is not called. If `initial` is supplied, returns the
-// result of applying `f` to `initial` and the first item in sequence, then
-// applying `f` to that result and the 2nd item, etc. If sequence contains no
-// items, returns `initial` and `f` is not called.
-//
-// Implements clojure reduce:
-// http://clojuredocs.org/clojure_core/clojure.core/reduce
-const reduce = (...args) => {
- const xs = reductions(...args);
- let x;
- for (x of xs) void(0);
- return x;
-};
-exports.reduce = reduce;
-
-const each = (f, sequence) => {
- for (let x of seq(sequence)) void(f(x));
-};
-exports.each = each;
-
-
-const inc = x => x + 1;
-// Returns the number of items in the sequence. `count(null)` && `count()`
-// returns `0`. Also works on strings, arrays, Maps & Sets.
-
-// Implements clojure count:
-// http://clojuredocs.org/clojure_core/clojure.core/count
-const count = polymorphic({
- null: _ => 0,
- void: _ => 0,
- indexed: indexed => indexed.length,
- map: map => map.size,
- set: set => set.size,
- default: xs => reduce(inc, 0, xs)
-});
-exports.count = count;
-
-// Returns `true` if sequence has no items.
-
-// Implements clojure empty?:
-// http://clojuredocs.org/clojure_core/clojure.core/empty_q
-const isEmpty = sequence => {
- // Treat `null` and `undefined` as empty sequences.
- if (sequence === null || sequence === void(0))
- return true;
-
- // If contains any item non empty so return `false`.
- for (let _ of sequence)
- return false;
-
- // If has not returned yet, there was nothing to iterate
- // so it's empty.
- return true;
-};
-exports.isEmpty = isEmpty;
-
-const and = (a, b) => a && b;
-
-// Returns true if `p(x)` is logical `true` for every `x` in sequence, else
-// `false`.
-//
-// Implements clojure every?:
-// http://clojuredocs.org/clojure_core/clojure.core/every_q
-const isEvery = (p, sequence) => {
- if (sequence !== null && sequence !== void(0)) {
- for (let item of sequence) {
- if (!p(item))
- return false;
- }
- }
- return true;
-};
-exports.isEvery = isEvery;
-
-// Returns the first logical true value of (p x) for any x in sequence,
-// else `null`.
-//
-// Implements clojure some:
-// http://clojuredocs.org/clojure_core/clojure.core/some
-const some = (p, sequence) => {
- if (sequence !== null && sequence !== void(0)) {
- for (let item of sequence) {
- if (p(item))
- return true;
- }
- }
- return null;
-};
-exports.some = some;
-
-// Returns a lazy sequence of the first `n` items in sequence, or all items if
-// there are fewer than `n`.
-//
-// Implements clojure take:
-// http://clojuredocs.org/clojure_core/clojure.core/take
-const take = (n, sequence) => n <= 0 ? empty() : seq(function* () {
- let count = n;
- for (let item of sequence) {
- yield item;
- count = count - 1;
- if (count === 0) break;
- }
-});
-exports.take = take;
-
-// Returns a lazy sequence of successive items from sequence while
-// `p(item)` returns `true`. `p` must be free of side-effects.
-//
-// Implements clojure take-while:
-// http://clojuredocs.org/clojure_core/clojure.core/take-while
-const takeWhile = (p, sequence) => seq(function* () {
- for (let item of sequence) {
- if (!p(item))
- break;
-
- yield item;
- }
-});
-exports.takeWhile = takeWhile;
-
-// Returns a lazy sequence of all but the first `n` items in
-// sequence.
-//
-// Implements clojure drop:
-// http://clojuredocs.org/clojure_core/clojure.core/drop
-const drop = (n, sequence) => seq(function* () {
- if (sequence !== null && sequence !== void(0)) {
- let count = n;
- for (let item of sequence) {
- if (count > 0)
- count = count - 1;
- else
- yield item;
- }
- }
-});
-exports.drop = drop;
-
-// Returns a lazy sequence of the items in sequence starting from the
-// first item for which `p(item)` returns falsy value.
-//
-// Implements clojure drop-while:
-// http://clojuredocs.org/clojure_core/clojure.core/drop-while
-const dropWhile = (p, sequence) => seq(function* () {
- let keep = false;
- for (let item of sequence) {
- keep = keep || !p(item);
- if (keep) yield item;
- }
-});
-exports.dropWhile = dropWhile;
-
-// Returns a lazy sequence representing the concatenation of the
-// suplied sequences.
-//
-// Implements clojure conact:
-// http://clojuredocs.org/clojure_core/clojure.core/concat
-const concat = (...sequences) => seq(function* () {
- for (let sequence of sequences)
- for (let item of sequence)
- yield item;
-});
-exports.concat = concat;
-
-// Returns the first item in the sequence.
-//
-// Implements clojure first:
-// http://clojuredocs.org/clojure_core/clojure.core/first
-const first = sequence => {
- if (sequence !== null && sequence !== void(0)) {
- for (let item of sequence)
- return item;
- }
- return null;
-};
-exports.first = first;
-
-// Returns a possibly empty sequence of the items after the first.
-//
-// Implements clojure rest:
-// http://clojuredocs.org/clojure_core/clojure.core/rest
-const rest = sequence => drop(1, sequence);
-exports.rest = rest;
-
-// Returns the value at the index. Returns `notFound` or `undefined`
-// if index is out of bounds.
-const nth = (xs, n, notFound) => {
- if (n >= 0) {
- if (isArray(xs) || isArguments(xs) || isString(xs)) {
- return n < xs.length ? xs[n] : notFound;
- }
- else if (xs !== null && xs !== void(0)) {
- let count = n;
- for (let x of xs) {
- if (count <= 0)
- return x;
-
- count = count - 1;
- }
- }
- }
- return notFound;
-};
-exports.nth = nth;
-
-// Return the last item in sequence, in linear time.
-// If `sequence` is an array or string or arguments
-// returns in constant time.
-// Implements clojure last:
-// http://clojuredocs.org/clojure_core/clojure.core/last
-const last = polymorphic({
- null: _ => null,
- void: _ => null,
- indexed: indexed => indexed[indexed.length - 1],
- map: xs => reduce((_, x) => x, xs),
- set: xs => reduce((_, x) => x, xs),
- default: xs => reduce((_, x) => x, xs)
-});
-exports.last = last;
-
-// Return a lazy sequence of all but the last `n` (default 1) items
-// from the give `xs`.
-//
-// Implements clojure drop-last:
-// http://clojuredocs.org/clojure_core/clojure.core/drop-last
-const dropLast = flip((xs, n=1) => seq(function* () {
- let ys = [];
- for (let x of xs) {
- ys.push(x);
- if (ys.length > n)
- yield ys.shift();
- }
-}));
-exports.dropLast = dropLast;
-
-// Returns a lazy sequence of the elements of `xs` with duplicates
-// removed
-//
-// Implements clojure distinct
-// http://clojuredocs.org/clojure_core/clojure.core/distinct
-const distinct = sequence => seq(function* () {
- let items = new Set();
- for (let item of sequence) {
- if (!items.has(item)) {
- items.add(item);
- yield item;
- }
- }
-});
-exports.distinct = distinct;
-
-// Returns a lazy sequence of the items in `xs` for which
-// `p(x)` returns false. `p` must be free of side-effects.
-//
-// Implements clojure remove
-// http://clojuredocs.org/clojure_core/clojure.core/remove
-const remove = (p, xs) => filter(complement(p), xs);
-exports.remove = remove;
-
-// Returns the result of applying concat to the result of
-// `map(f, xs)`. Thus function `f` should return a sequence.
-//
-// Implements clojure mapcat
-// http://clojuredocs.org/clojure_core/clojure.core/mapcat
-const mapcat = (f, sequence) => seq(function* () {
- const sequences = map(f, sequence);
- for (let sequence of sequences)
- for (let item of sequence)
- yield item;
-});
-exports.mapcat = mapcat;