UNPKG

art-standard-lib

Version:

The Standard Library for JavaScript that aught to be.

360 lines (290 loc) 11.1 kB
// Generated by CoffeeScript 1.12.7 (function() { var Iteration, compactFlatten, deepArrayEach, isArrayOrArguments, isFunction, isObject, isPlainArray, isPlainObject, log, mergeInto, ref, ref1, slice = [].slice; ref = require('./Core'), compactFlatten = ref.compactFlatten, deepArrayEach = ref.deepArrayEach, isArrayOrArguments = ref.isArrayOrArguments, mergeInto = ref.mergeInto; ref1 = require('./TypesExtended'), isPlainObject = ref1.isPlainObject, isObject = ref1.isObject, isFunction = ref1.isFunction, isPlainArray = ref1.isPlainArray; log = function() { var args, ref2; args = 1 <= arguments.length ? slice.call(arguments, 0) : []; return (ref2 = Neptune.Art.StandardLib).log.apply(ref2, args); }; module.exports = Iteration = (function() { var arrayIterableTest, emptyOptions, invokeNormalizedIteration, normalizedArray, normalizedEach, normalizedEachWhile, normalizedFind, normalizedInject, normalizedObject, returnFirst, returnSecond; function Iteration() {} returnFirst = function(a) { return a; }; returnSecond = function(a, b) { return b; }; arrayIterableTest = function(source) { return (source != null ? source.length : void 0) >= 0; }; emptyOptions = {}; /* COMMON API: IN: (source, withBlock = returnFirst) -> IN: (source, options) -> IN: (source, into, withBlock = returnFirst) -> IN: (source, into, options) -> source: array-like (see arrayIterableTest) use indexes to iterate non-null options: with: withBlock when: whenBlock into: into withBlock: (value, key, into, whenBlockResult) -> value Generally, this generates the 'value' used for each part of the iteration. When constructing a new collection, this is the value for each entry. 'find' and 'reduce' use this differently. OUT: into TODO: - support ES6 iterables and iterators - flatten: true - if source is an array, recurse into any sub-arrays - compact: effectively `when: (v) -> v?` except you can also have your own when-function in addition, run after this one. - skip: N - skip the first N values - short: N - stop short N values - until: () -> T/F - same args as withBlock, loop stops when true, executed after first withBlock - while: () -> T/F - same args as withBlock, loop stops when false, executed before first whenBlock - by: N - N>0: only stop at every Nth value N<0: iterate in reverse order, only stop at every abs(N)th value */ /* each differences from the common-api: 1) into defaults to source */ Iteration.each = function(source, a, b) { return invokeNormalizedIteration(normalizedEach, source, a, b); }; normalizedEach = function(source, into, withBlock, options) { var i, j, k, len, len1, v, w, whenBlock; if (into === void 0) { into = source; } if (options) { whenBlock = options.when; } if (arrayIterableTest(source)) { if (whenBlock) { for (k = i = 0, len = source.length; i < len; k = ++i) { v = source[k]; if (w = whenBlock(v, k)) { withBlock(v, k, into, w); } } } else { for (k = j = 0, len1 = source.length; j < len1; k = ++j) { v = source[k]; withBlock(v, k, into); } } } else if (source != null) { if (whenBlock) { for (k in source) { v = source[k]; if (w = whenBlock(v, k)) { withBlock(v, k, into, w); } } } else { for (k in source) { v = source[k]; withBlock(v, k, into); } } } return into; }; /* eachWhile differences from the common-api: 1) into defaults to source 2) stops when withBlock returns false */ Iteration.eachWhile = function(source, a, b) { return invokeNormalizedIteration(normalizedEachWhile, source, a, b); }; normalizedEachWhile = function(source, into, withBlock, options) { var i, j, k, len, len1, v, w, whenBlock; if (into === void 0) { into = source; } if (options) { whenBlock = options.when; } if (arrayIterableTest(source)) { if (whenBlock) { for (k = i = 0, len = source.length; i < len; k = ++i) { v = source[k]; if (w = whenBlock(v, k)) { if (!withBlock(v, k, into, w)) { break; } } } } else { for (k = j = 0, len1 = source.length; j < len1; k = ++j) { v = source[k]; if (!withBlock(v, k, into)) { break; } } } } else if (source != null) { if (whenBlock) { for (k in source) { v = source[k]; if (w = whenBlock(v, k)) { if (!withBlock(v, k, into, w)) { break; } } } } else { for (k in source) { v = source[k]; if (!withBlock(v, k, into)) { break; } } } } return into; }; /* reduce differences from the common-api: 1) The with-block has a different argument order. Into is passed first instead of last: with: (into, value, key, whenReturnValue) -> This allows you to drop-in functions that take two args and reduce them to one like: Math.max add = (a, b) -> a + b The default with-block still returns value (which is now the second argument). 1) if into starts out undefined: for v = the first value (if whenBlock is present, the first value when whenBlock is true) into = v skip: withBlock 2) when withBlock is executed, into is updated: into = withBlock() */ Iteration.reduce = function(source, a, b) { return invokeNormalizedIteration(normalizedInject, source, a, b); }; normalizedInject = function(source, into, withBlock, options) { var intoSet; if (source == null) { return into; } normalizedEach(source, void 0, (intoSet = into !== void 0) ? function(v, k, __, w) { return into = withBlock(into, v, k, w); } : function(v, k, __, w) { return into = intoSet ? withBlock(into, v, k, w) : (intoSet = true, v); }, options); return into; }; /* object differences from the common-api: IN: options.key: (value, key, into, whenBlockResult) -> value 1) into defaults to a new object ({}) (if into == undefined) 2) when withBlock is executed, into is updated: if source is array-like: into[v] = withBlock() else into[k] = withBlock() */ Iteration.object = function(source, a, b) { return invokeNormalizedIteration(normalizedObject, source, a, b); }; normalizedObject = function(source, into, withBlock, options) { var keyFunction; keyFunction = options.key || options.withKey || (arrayIterableTest(source) ? returnFirst : returnSecond); return normalizedEach(source, into != null ? into : {}, function(v, k, into, w) { return into[keyFunction(v, k, into, w)] = withBlock(v, k, into, w); }, options); }; /* array differences from the common-api: 1) into defaults to a new array ([]) (if into == undefined) 2) when withBlock is executed, into is updated: into.push withBlock() */ Iteration.array = function(source, a, b) { return invokeNormalizedIteration(normalizedArray, source, a, b); }; normalizedArray = function(source, into, withBlock, options) { return normalizedEach(source, into != null ? into : [], function(v, k, into, w) { return into.push(withBlock(v, k, into, w)); }, options); }; /* differs from common api: 1) returns the last value returned by withBlock or undefined if withBlock was never executed 2) stops if a) whenBlock?: and it returned true (stops after withBlock is evaluated) b) !whenBlock?: withBlock returns a truish value */ Iteration.find = function(source, a, b) { return invokeNormalizedIteration(normalizedFind, source, a, b); }; normalizedFind = function(source, into, withBlock, options) { var found; normalizedEachWhile(source, found = void 0, options.whenBlock ? function(v, k, into, w) { found = withBlock(v, k, null, w); return false; } : function(v, k, into, w) { return !(found = withBlock(v, k, null, w)); }, options); return found; }; /* Normalizes input params for the 'iteration' function. Since this normalizes multile params, and therefor would need to return an new array or new object otherwise, we pass IN the iteration function and pass the params directly to it. This keeps the computed params on the stack and doesn't create new objects. IN signature 1: (iteration, source, into, withBlock) -> IN signature 2: (iteration, source, into, options) -> IN signature 3: (iteration, source, withBlock) -> IN signature 4: (iteration, source, options) -> IN signature 5: (iteration, source) -> IN: iteration: (source, into, withBlock, options) -> out The iteration function is invoked last with the computed args. Its retults are returned. IN: source: passed directly through from inputs into: passed directly through from inputs OR from options.into withBlock: passed directly through from inputs OR from options.with options: passed direftly through from inputs OR {} (guaranteed to be set and a plainObject) source: the source collection to be iterated over. Passed streight through. into: passed through to 'iteration' withBlock: passed through to 'iteration' options: passed through to 'iteration' AND: into: set 'into' from the options object with: set 'withBlock' from the options object OUT: out */ invokeNormalizedIteration = function(iteration, source, a, b) { var into, options, withBlock; options = b ? (into = a, b) : a; if (isPlainObject(options)) { if (into == null) { into = options.into; } withBlock = options["with"]; } else { if (isFunction(options)) { withBlock = options; } options = emptyOptions; } return iteration(source, into, withBlock || returnFirst, options); }; return Iteration; })(); }).call(this); //# sourceMappingURL=Iteration.js.map