+90
| 'use strict' | ||
| var forEach = require('transduce/array/forEach') | ||
| module.exports = function(_r){ | ||
| // Array Functions | ||
| // --------------- | ||
| _r.mixin({ | ||
| forEach: forEach, | ||
| each: forEach, | ||
| find: find, | ||
| detect: find, | ||
| every: every, | ||
| all: every, | ||
| some: some, | ||
| any: some, | ||
| contains: contains, | ||
| include: contains, | ||
| findWhere: findWhere, | ||
| push: require('transduce/array/push'), | ||
| unshift: require('transduce/array/unshift'), | ||
| at: at, | ||
| slice: require('transduce/array/slice'), | ||
| initial: require('transduce/array/initial'), | ||
| last: last | ||
| }) | ||
| var iteratee = _r.iteratee, | ||
| resolveSingleValue = _r.resolveSingleValue, | ||
| _ = _r._ | ||
| // Return the first value which passes a truth test. Aliased as `detect`. | ||
| var _find = require('transduce/array/find') | ||
| function find(predicate) { | ||
| /*jshint validthis:true*/ | ||
| resolveSingleValue(this) | ||
| return _find(iteratee(predicate)) | ||
| } | ||
| // Determine whether all of the elements match a truth test. | ||
| // Aliased as `all`. | ||
| var _every = require('transduce/array/every') | ||
| function every(predicate) { | ||
| /*jshint validthis:true*/ | ||
| resolveSingleValue(this) | ||
| return _every(iteratee(predicate)) | ||
| } | ||
| // Determine if at least one element in the object matches a truth test. | ||
| // Aliased as `any`. | ||
| var _some = require('transduce/array/some') | ||
| function some(predicate) { | ||
| /*jshint validthis:true*/ | ||
| resolveSingleValue(this) | ||
| return _some(iteratee(predicate)) | ||
| } | ||
| // Determine if contains a given value (using `===`). | ||
| // Aliased as `include`. | ||
| function contains(target) { | ||
| /*jshint validthis:true*/ | ||
| return some.call(this, function(x){ return x === target }) | ||
| } | ||
| // Convenience version of a common use case of `find`: getting the first object | ||
| // containing specific `key:value` pairs. | ||
| function findWhere(attrs) { | ||
| /*jshint validthis:true*/ | ||
| return find.call(this, _.matches(attrs)) | ||
| } | ||
| // Retrieves the value at the given index. Resolves as single value. | ||
| var _slice = require('transduce/array/slice') | ||
| function at(idx){ | ||
| /*jshint validthis:true*/ | ||
| resolveSingleValue(this) | ||
| return _slice(idx, idx+1) | ||
| } | ||
| // Get the last element. Passing **n** will return the last N values. | ||
| // Note that no items will be sent until completion. | ||
| var _last = require('transduce/array/last') | ||
| function last(n) { | ||
| if(n === void 0){ | ||
| /*jshint validthis:true*/ | ||
| resolveSingleValue(this) | ||
| } | ||
| return _last(n) | ||
| } | ||
| } |
+90
| 'use strict' | ||
| var util = require('transduce/core/util'), | ||
| merge = util.objectMerge, | ||
| isArray = util.isArray, | ||
| isFunction = util.isFunction | ||
| var _r = function(obj, transform) { | ||
| if (_r.as(obj)){ | ||
| if(transform === void 0){ | ||
| return obj | ||
| } | ||
| var wrappedFns = obj._wrappedFns.slice() | ||
| wrappedFns.push(transform) | ||
| var copy = new _r(obj._wrapped, wrappedFns) | ||
| copy._opts = merge({}, obj._opts) | ||
| return copy | ||
| } | ||
| if (!(_r.as(this))) return new _r(obj, transform) | ||
| if(_r.as(transform)){ | ||
| this._opts = merge({}, transform._opts) | ||
| transform = transform._wrappedFns | ||
| } else { | ||
| this._opts = {} | ||
| } | ||
| if(isFunction(transform)){ | ||
| this._wrappedFns = [transform] | ||
| } else if(isArray(transform)){ | ||
| this._wrappedFns = transform | ||
| } else { | ||
| this._wrappedFns = [] | ||
| } | ||
| this._wrapped = _r.wrap.call(this, obj) | ||
| } | ||
| _r.VERSION = '0.6.0' | ||
| // Export for browser or Common-JS | ||
| // Save the previous value of the `_r` variable. | ||
| var previous_r, root | ||
| if(typeof window !== 'undefined'){ | ||
| /*global window*/ | ||
| var root = window | ||
| previous_r = root._r | ||
| root._r = _r | ||
| _r._ = root._ | ||
| } else { | ||
| root = {} | ||
| } | ||
| module.exports = _r | ||
| // Returns the value if it is a chained transformation, else null | ||
| _r.as = function(value){ | ||
| return value instanceof _r ? value : null | ||
| } | ||
| // Run Underscore.js in *noConflict* mode, returning the `_` variable to its | ||
| // previous owner. Returns a reference to the Underscore object. | ||
| _r.noConflict = function() { | ||
| root._r = previous_r | ||
| return this | ||
| } | ||
| // Returns a new chained instance using current transformation, but | ||
| // wrapping the given source | ||
| _r.prototype.withSource = function(obj){ | ||
| return _r(obj, this) | ||
| } | ||
| // Add your own custom transducers to the Underscore.transducer object. | ||
| _r.mixin = function(obj) { | ||
| var name, fn | ||
| for(name in obj){ | ||
| fn = obj[name] | ||
| if(typeof fn === 'function'){ | ||
| _r[name] = fn | ||
| _r.prototype[name] = _method(fn) | ||
| } | ||
| } | ||
| } | ||
| function _method(func){ | ||
| return function() { | ||
| var method = func.apply(this, arguments) | ||
| return _r(this, method) | ||
| } | ||
| } |
+308
| 'use strict' | ||
| var dispatcher = require('redispatch') | ||
| module.exports = function(_r){ | ||
| var _ = _r._, | ||
| as = _r.as, | ||
| // sentinel to ignore wrapped objects (maintain only last item) | ||
| IGNORE = _r.IGNORE = {} | ||
| // Transducer Functions | ||
| // -------------------- | ||
| var value = _r.value = dispatcher(), | ||
| wrap = _r.wrap = dispatcher(), | ||
| unwrap = _r.unwrap = dispatcher(), | ||
| empty = _r.empty = dispatcher(), | ||
| append = _r.append = dispatcher(), | ||
| reduce = _r.reduce = dispatcher(), | ||
| _reduce = require('transduce/core/reduce'), | ||
| _unreduced = require('transduce/core/unreduced'), | ||
| transduce = _r.transduce = dispatcher(), | ||
| _transduce = require('transduce/core/transduce'), | ||
| into = _r.into = dispatcher(), | ||
| transducer = _r.transducer = dispatcher(), | ||
| iterator = _r.iterator = dispatcher(), | ||
| _iterable = require('transduce/core/iterable'), | ||
| _protocols = require('transduce/core/protocols'), | ||
| toArray = _r.toArray = dispatcher(), | ||
| _toArray = require('transduce/core/into')([]), | ||
| _util = require('transduce/core/util'), | ||
| iteratee = _r.iteratee = dispatcher() | ||
| _r.resolveSingleValue = resolveSingleValue | ||
| _r.resolveMultipleValues = resolveMultipleValues | ||
| _r.reduced = require('transduce/core/reduced') | ||
| _r.isReduced = require('transduce/core/isReduced') | ||
| _r.foldl = reduce | ||
| _r.inject = reduce | ||
| _r.deref = unwrap | ||
| _r.conj = append | ||
| _r.conjoin = append | ||
| _r.dispatch = dispatch | ||
| var compose = _r.compose = require('transduce/core/compose') | ||
| _r.transformer = require('transduce/core/transformer') | ||
| _r.iterable = _iterable | ||
| _r.protocols = _protocols | ||
| _r.isFunction = _util.isFunction | ||
| var isArray = _r.isArray = _util.isArray | ||
| var isString = _r.isString = _util.isString | ||
| _r.isRegExp = _util.isRegExp | ||
| _r.isNumber = _util.isNumber | ||
| _r.isUndefined = _util.isUndefined | ||
| _r.arrayPush = _util.arrayPush | ||
| _r.objectMerge = _util.objectMerge | ||
| _r.stringAppend = _util.stringAppend | ||
| var identity = _r.identity = _util.identity | ||
| // Dispatchers | ||
| // ----------- | ||
| // Resolves the value of the wrapped object, similar to underscore. | ||
| // Returns an array, or single value (to match underscore API) | ||
| // depending on whether the chained transformation resolves to single value. | ||
| value.register(function(self){ | ||
| if(!self._opts.resolveSingleValue){ | ||
| return self.into() | ||
| } | ||
| var ret = self.into(IGNORE) | ||
| return ret === IGNORE ? void 0 : ret | ||
| }) | ||
| _r.prototype.value = function(){ | ||
| return value(this) | ||
| } | ||
| // Helper to mark transducer to expect single value when | ||
| // resolving. Only valid when chaining, but this should be passed | ||
| // when called as a function | ||
| function resolveSingleValue(self){ | ||
| _resolveSingleValue(self, true) | ||
| } | ||
| // Helper to mark transducer to expect multiple values when | ||
| // resolving. Only valid when chaining, but this should be passed | ||
| // when called as a function. | ||
| function resolveMultipleValues(self){ | ||
| _resolveSingleValue(self, false) | ||
| } | ||
| function _resolveSingleValue(self, single){ | ||
| if(as(self)){ | ||
| self._opts.resolveSingleValue = single | ||
| } | ||
| } | ||
| // Composes and returns the underlying wrapped functions for give chained object | ||
| transducer.register(function(self){ | ||
| var fns = self._wrappedFns | ||
| return fns.length ? compose.apply(null, fns) : identity | ||
| }) | ||
| _r.prototype.transducer = _r.prototype.compose = function() { | ||
| return transducer(this) | ||
| } | ||
| reduce.register(function(xf, init, coll) { | ||
| if(as(xf)){ | ||
| xf = transducer(xf) | ||
| } | ||
| if (coll === null || coll === void 0) coll = empty(coll) | ||
| return _reduce(xf, init, coll) | ||
| }) | ||
| // Calls transduce using the chained transformation if function not passed | ||
| _r.prototype.reduce = function(init, coll){ | ||
| if(coll === void 0){ | ||
| coll = this._wrapped | ||
| } | ||
| return reduce(this, init, coll) | ||
| } | ||
| transduce.register(function(xf, f, init, coll){ | ||
| if(as(xf)){ | ||
| xf = transducer(xf) | ||
| } | ||
| return unwrap(_transduce(xf, f, init, coll)) | ||
| }) | ||
| // Calls transduce using the chained transformation | ||
| _r.prototype.transduce = function(f, init, coll){ | ||
| if(coll === void 0){ | ||
| coll = this._wrapped | ||
| } | ||
| return transduce(this, f, init, coll) | ||
| } | ||
| // Returns a new coll consisting of to-coll with all of the items of | ||
| // from-coll conjoined. A transducer (step function) may be supplied. | ||
| into.register(function(to, xf, from){ | ||
| if(from === void 0){ | ||
| from = xf | ||
| xf = void 0 | ||
| } | ||
| if(from === void 0){ | ||
| from = empty() | ||
| } | ||
| if(as(xf)){ | ||
| xf = transducer(xf) | ||
| } | ||
| if(to === void 0){ | ||
| to = empty(from) | ||
| } | ||
| if(xf === void 0){ | ||
| return reduce(append, to, from) | ||
| } | ||
| return transduce(xf, append, to, from) | ||
| }) | ||
| // Calls into using the chained transformation | ||
| _r.prototype.into = function(to, from){ | ||
| if(from === void 0){ | ||
| from = this._wrapped | ||
| } | ||
| return into(to, this, from) | ||
| } | ||
| // Returns a new collection of the empty value of the from collection | ||
| toArray.register(function(xf, from){ | ||
| if(as(xf)){ | ||
| xf = transducer(xf) | ||
| } | ||
| if(arguments.length === 1){ | ||
| return _toArray(xf) | ||
| } | ||
| return _toArray(xf, from) | ||
| }) | ||
| // calls toArray with chained transformation and optional wrapped object | ||
| _r.prototype.toArray = function(from){ | ||
| if(from === void 0){ | ||
| from = this._wrapped | ||
| } | ||
| return toArray(this, from) | ||
| } | ||
| // Wraps a value used as source for use during chained transformation. | ||
| // | ||
| // Default returns value, or _r.empty() if undefined. | ||
| // | ||
| // Dispatch function. To support different types, | ||
| // call _r.unwrap.register | ||
| wrap.register(function(value){ | ||
| if(isString(value)){ | ||
| value = [value] | ||
| } else if(value === null || value === void 0){ | ||
| value = empty() | ||
| } | ||
| return value | ||
| }) | ||
| // Unwraps (deref) a possibly wrapped value | ||
| // Default unwraps values created with _r.reduced, | ||
| // or calls value() on chained _r transformations, | ||
| // otherwise returns parameter. | ||
| // | ||
| // Dispatch function. To support different types, | ||
| // call _r.unwrap.register | ||
| unwrap.register(function(value){ | ||
| if(as(value)){ | ||
| return value.value() | ||
| } | ||
| return _unreduced(value) | ||
| }) | ||
| // Returns an iterator that has next function | ||
| // and returns {value, done}. Default looks for | ||
| // object with iterator Symbol (or '@@iterator'). | ||
| // This is available with _r.iterator.Symbol | ||
| // | ||
| // Dispatch function. To support different types | ||
| // call _r.iterator.register and supply function that returns | ||
| // an iterator after checking the input using appropriate | ||
| // predicates. Return undefined if not supported, so other | ||
| // dispatched functions can be checked | ||
| iterator.register(function(value){ | ||
| return _iterable(value)[_protocols.iterator]() | ||
| }) | ||
| // Mostly internal function that generates a callback from the given value. | ||
| // For use with generating callbacks for map, filter, find, etc. | ||
| // | ||
| // Default returns _.iteratee. | ||
| // | ||
| // Dispatch function. To support different types | ||
| // call _r.iteratee.register and supply function that returns | ||
| // a callback after checking the input using appropriate | ||
| // predicates. Return undefined if not supported, so other | ||
| // dispatched functions can be checked | ||
| iteratee.register(function(value){ | ||
| if(as(value)){ | ||
| return _riteratee(value) | ||
| } | ||
| return _.iteratee(value) | ||
| }) | ||
| function _riteratee(value){ | ||
| return function(item){ | ||
| return value.withSource(item).value() | ||
| } | ||
| } | ||
| // Returns empty object of the same type as argument. | ||
| // Default returns [] if isArray or undefined, {} if _.isObject | ||
| // and an internal sentinel to ignore otherwise | ||
| // | ||
| // Dispatch function. To support different types | ||
| // call _r.empty.register and supply function that returns | ||
| // an empty object after checking the input using appropriate | ||
| // predicates. Return undefined if not supported, so other | ||
| // dispatched functions can be checked | ||
| empty.register(function(obj){ | ||
| if(obj === void 0 || isArray(obj) || iterator(obj)){ | ||
| return [] // array if not specified or from array | ||
| } else if(_.isObject(obj)){ | ||
| return {} // object if from object | ||
| } | ||
| // ignore by default. Default append just maintains last item. | ||
| return IGNORE | ||
| }) | ||
| // Appends (conjoins) the item to the collection, and returns collection | ||
| // | ||
| // Dispatch function. To support different types | ||
| // call _r.append.register and supply function that append to the object | ||
| // (first param) with the item and optional key after checking the input | ||
| // using appropriate predicates. | ||
| // | ||
| // Return undefined if not supported, so other dispatched functions can be checked | ||
| append.register(function(obj, item){ | ||
| if(isArray(obj)){ | ||
| obj.push(item) | ||
| return obj | ||
| } | ||
| // just maintain last item | ||
| return item | ||
| }) | ||
| // Reducer that dispatches to empty, unwrap and append | ||
| function Dispatch(){} | ||
| Dispatch.prototype.init = empty | ||
| Dispatch.prototype.result = unwrap | ||
| Dispatch.prototype.step = append | ||
| function dispatch(){ | ||
| return new Dispatch() | ||
| } | ||
| } |
| 'use strict' | ||
| var symIterator = require('transduce/core/protocols').iterator | ||
| module.exports = function(_r){ | ||
| _r.generate = generate | ||
| // Transduces the current chained object by using the chained trasnformation | ||
| // and an iterator created with the callback | ||
| _r.prototype.generate = function(callback, callToInit){ | ||
| return this.withSource(generate(callback, callToInit)) | ||
| } | ||
| // Creates an (duck typed) iterator that calls the provided next callback repeatedly | ||
| // and uses the return value as the next value of the iterator. | ||
| // Marks iterator as done if the next callback returns undefined (returns nothing) | ||
| // Can be used to as a source obj to reduce, transduce etc | ||
| function generate(callback, callToInit){ | ||
| var gen = {} | ||
| gen[symIterator] = function(){ | ||
| var next = callToInit ? callback() : callback | ||
| return { | ||
| next: function(){ | ||
| var value = next() | ||
| return (value === void 0) ? {done: true} : {done: false, value: value} | ||
| } | ||
| } | ||
| } | ||
| return gen | ||
| } | ||
| } |
+17
| 'use strict' | ||
| module.exports = function(libs, _r){ | ||
| var i = 0, len = libs.length, lib | ||
| if(_r === void 0){ | ||
| _r = require('./base') | ||
| } | ||
| for(; i < len; i++){ | ||
| lib = libs[i] | ||
| // only import if included in build | ||
| if(typeof lib === 'function'){ | ||
| lib(_r) | ||
| } | ||
| } | ||
| return _r | ||
| } |
+29
| 'use strict' | ||
| var _max = require('transduce/math/max'), | ||
| _min = require('transduce/math/min') | ||
| module.exports = function(_r){ | ||
| // Math Functions | ||
| // -------------------- | ||
| _r.mixin({ | ||
| max: max, | ||
| min: min | ||
| }) | ||
| var iteratee = _r.iteratee, | ||
| resolveSingleValue = _r.resolveSingleValue | ||
| // Return the maximum element (or element-based computation). | ||
| function max(f) { | ||
| /*jshint validthis:true */ | ||
| resolveSingleValue(this) | ||
| return _max(iteratee(f)) | ||
| } | ||
| // Return the minimum element (or element-based computation). | ||
| function min(f) { | ||
| /*jshint validthis:true */ | ||
| resolveSingleValue(this) | ||
| return _min(iteratee(f)) | ||
| } | ||
| } |
+73
| 'use strict' | ||
| var tap = require('transduce/push/tap'), | ||
| _asCallback = require('transduce/push/asCallback'), | ||
| _asyncCallback = require('transduce/push/asyncCallback') | ||
| module.exports = function(_r){ | ||
| _r.mixin({tap: tap}) | ||
| _r.asCallback = asCallback | ||
| _r.asyncCallback = asyncCallback | ||
| var as = _r.as, | ||
| dispatch = _r.dispatch, | ||
| transducer = _r.transducer | ||
| // Creates a callback that starts a transducer process and accepts | ||
| // parameter as a new item in the process. Each item advances the state | ||
| // of the transducer. If the transducer exhausts due to early termination, | ||
| // all subsequent calls to the callback will no-op and return the computed result. | ||
| // | ||
| // If the callback is called with no argument, the transducer terminates, | ||
| // and all subsequent calls will no-op and return the computed result. | ||
| // | ||
| // The callback returns undefined until completion. Once completed, the result | ||
| // is always returned. | ||
| // | ||
| // If init is defined, maintains last value and does not buffer results. | ||
| // If init is provided, it is dispatched | ||
| function asCallback(xf, init){ | ||
| if(as(xf)){ | ||
| xf = transducer(xf) | ||
| } | ||
| var reducer | ||
| if(init !== void 0){ | ||
| reducer = dispatch() | ||
| } | ||
| return _asCallback(xf, reducer) | ||
| } | ||
| _r.prototype.asCallback = function(init){ | ||
| return asCallback(this, init) | ||
| } | ||
| // Creates an async callback that starts a transducer process and accepts | ||
| // parameter cb(err, item) as a new item in the process. The returned callback | ||
| // and the optional continuation follow node conventions with fn(err, item). | ||
| // | ||
| // Each item advances the state of the transducer, if the continuation | ||
| // is provided, it will be called on completion or error. An error will terminate | ||
| // the transducer and be propagated to the continuation. If the transducer | ||
| // exhausts due to early termination, any further call will be a no-op. | ||
| // | ||
| // If the callback is called with no item, it will terminate the transducer process. | ||
| // | ||
| // If init is defined, maintains last value and does not buffer results. | ||
| // If init is provided, it is dispatched | ||
| function asyncCallback(xf, continuation, init){ | ||
| if(as(xf)){ | ||
| xf = transducer(xf) | ||
| } | ||
| var reducer | ||
| if(init !== void 0){ | ||
| reducer = dispatch() | ||
| } | ||
| return _asyncCallback(xf, continuation, reducer) | ||
| } | ||
| _r.prototype.asyncCallback = function(continuation, init){ | ||
| return asyncCallback(this, continuation, init) | ||
| } | ||
| } |
| 'use strict' | ||
| var seq = require('transduce/core/sequence'), | ||
| symbol = require('transduce/core/protocols').iterator | ||
| module.exports = function(_r){ | ||
| // Returns a new collection of the empty value of the from collection | ||
| _r.sequence = sequence | ||
| function sequence(xf, from){ | ||
| if(_r.as(xf)){ | ||
| xf = _r.transducer(xf) | ||
| } | ||
| return seq(xf, from) | ||
| } | ||
| // calls sequence with chained transformation and optional wrapped object | ||
| _r.prototype.sequence = function(from){ | ||
| if(from === void 0){ | ||
| from = this._wrapped | ||
| } | ||
| return sequence(this, from) | ||
| } | ||
| _r.prototype[symbol] = function(){ | ||
| return _r.iterator(this.sequence()) | ||
| } | ||
| } |
| 'use strict' | ||
| module.exports = function(_r){ | ||
| // String Functions | ||
| // -------------------- | ||
| _r.mixin({ | ||
| split: require('transduce/string/split'), | ||
| join: join, | ||
| nonEmpty: require('transduce/string/nonEmpty'), | ||
| lines: require('transduce/string/lines'), | ||
| chars: require('transduce/string/chars'), | ||
| words: require('transduce/string/words') | ||
| }) | ||
| var _join = require('transduce/string/join') | ||
| function join(separator){ | ||
| /*jshint validthis:true */ | ||
| _r.resolveSingleValue(this) | ||
| return _join(separator) | ||
| } | ||
| } |
+147
| 'use strict' | ||
| var slice = Array.prototype.slice | ||
| module.exports = function(_r){ | ||
| // Base Transducers | ||
| // ---------------- | ||
| _r.mixin({ | ||
| map: map, | ||
| collect: map, | ||
| filter: filter, | ||
| select: filter, | ||
| remove: remove, | ||
| reject: remove, | ||
| take: take, | ||
| first: take, | ||
| head: take, | ||
| takeWhile: takeWhile, | ||
| drop: drop, | ||
| rest: drop, | ||
| tail: drop, | ||
| dropWhile: dropWhile, | ||
| cat: cat, | ||
| mapcat: mapcat, | ||
| partitionAll: partitionAll, | ||
| chunkAll: partitionAll, | ||
| partitionBy: partitionBy, | ||
| compact: compact, | ||
| invoke: invoke, | ||
| pluck: pluck, | ||
| where: where | ||
| }) | ||
| var iteratee = _r.iteratee, | ||
| _ = _r._, | ||
| util = require('transduce/core/util'), | ||
| isFunction = util.isFunction, | ||
| identity = util.identity | ||
| // Return the results of applying the iteratee to each element. | ||
| var _map = require('transduce/transducers/map') | ||
| function map(f) { | ||
| return _map(iteratee(f)) | ||
| } | ||
| // Return all the elements that pass a truth test. | ||
| // Aliased as `select`. | ||
| var _filter = require('transduce/transducers/filter') | ||
| function filter(predicate) { | ||
| return _filter(iteratee(predicate)) | ||
| } | ||
| // Return all the elements for which a truth test fails. | ||
| var _remove = require('transduce/transducers/remove') | ||
| function remove(predicate) { | ||
| return _remove(iteratee(predicate)) | ||
| } | ||
| // Get the first element of an array. Passing **n** will return the first N | ||
| // values in the array. Aliased as `head` and `take`. | ||
| var _take = require('transduce/transducers/take') | ||
| function take(n) { | ||
| if(n === void 0){ | ||
| /*jshint validthis:true*/ | ||
| _r.resolveSingleValue(this) | ||
| n = 1 | ||
| } else { | ||
| n = (n > 0) ? n : 0 | ||
| } | ||
| return _take(n) | ||
| } | ||
| // takes items until predicate returns false | ||
| var _takeWhile = require('transduce/transducers/takeWhile') | ||
| function takeWhile(predicate) { | ||
| return _takeWhile(iteratee(predicate)) | ||
| } | ||
| // Returns everything but the first entry. Aliased as `tail` and `drop`. | ||
| // Passing an **n** will return the rest N values. | ||
| var _drop = require('transduce/transducers/drop') | ||
| function drop(n) { | ||
| n = (n === void 0) ? 1 : (n > 0) ? n : 0 | ||
| return _drop(n) | ||
| } | ||
| // Drops items while the predicate returns true | ||
| var _dropWhile = require('transduce/transducers/dropWhile') | ||
| function dropWhile(predicate) { | ||
| return _dropWhile(iteratee(predicate)) | ||
| } | ||
| // Concatenating transducer. | ||
| // NOTE: unlike libraries, cat should be called as a function to use. | ||
| // _r.cat() not _r.cat | ||
| var _cat = require('transduce/transducers/cat') | ||
| function cat(){ | ||
| return _cat | ||
| } | ||
| // mapcat. | ||
| // Composition of _r.map(f) and _r.cat() | ||
| var _mapcat = require('transduce/transducers/mapcat') | ||
| function mapcat(f){ | ||
| return _mapcat(iteratee(f)) | ||
| } | ||
| // Partitions the source into arrays of size n | ||
| // When transformer completes, the array will be stepped with any remaining items. | ||
| // Alias chunkAll | ||
| var _partitionAll = require('transduce/transducers/partitionAll') | ||
| function partitionAll(n){ | ||
| return _partitionAll(n) | ||
| } | ||
| // Partitions the source into sub arrays while the value of the function | ||
| // changes equality. | ||
| var _partitionBy = require('transduce/transducers/partitionBy') | ||
| function partitionBy(f){ | ||
| return _partitionBy(iteratee(f)) | ||
| } | ||
| // Trim out all falsy values from an array. | ||
| function compact() { | ||
| return filter(identity) | ||
| } | ||
| // Invoke a method (with arguments) on every item in a collection. | ||
| function invoke(method) { | ||
| var args = slice.call(arguments, 2), | ||
| isFunc = isFunction(method) | ||
| return map(function(value) { | ||
| return (isFunc ? method : value[method]).apply(value, args) | ||
| }) | ||
| } | ||
| // Convenience version of a common use case of `map`: fetching a property. | ||
| function pluck(key) { | ||
| return map(_.property(key)) | ||
| } | ||
| // Convenience version of a common use case of `filter`: selecting only objects | ||
| // containing specific `key:value` pairs. | ||
| function where(attrs) { | ||
| return filter(_.matches(attrs)) | ||
| } | ||
| } |
| 'use strict' | ||
| var _unique = require('transduce/transducers/unique'), | ||
| _dedupe = require('transduce/transducers/dedupe') | ||
| module.exports = function(_r){ | ||
| // Array Functions | ||
| // --------------- | ||
| _r.mixin({ | ||
| unique: unique, | ||
| uniq: unique | ||
| }) | ||
| var _ = _r._, | ||
| iteratee = _r.iteratee | ||
| // Produce a duplicate-free version of the array. If the array has already | ||
| // been sorted, you have the option of using a faster algorithm. | ||
| // Aliased as `unique`. | ||
| function unique(isSorted, f) { | ||
| if (isSorted !== true && isSorted !== false) { | ||
| f = isSorted | ||
| isSorted = false | ||
| } | ||
| if(isSorted){ | ||
| return _dedupe() | ||
| } | ||
| if (f !== void 0) f = iteratee(f) | ||
| return _unique(f) | ||
| } | ||
| } |
| 'use strict' | ||
| module.exports = function(_r){ | ||
| var _ = _r._ || {} | ||
| _r._ = _ | ||
| _.debounce = require('lodash-node/compat/function/debounce') | ||
| _.throttle = require('lodash-node/compat/function/throttle') | ||
| } |
+80
| 'use strict' | ||
| // Based on Underscore.js 1.7.0 | ||
| // http://underscorejs.org | ||
| // | ||
| // Which is distributed under MIT License: | ||
| // Underscore.js > (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors | ||
| // Underscore.js > Underscore may be freely distributed under the MIT license. | ||
| var util = require('transduce/core/util'), | ||
| isFunction = util.isFunction, | ||
| isArray = util.isArray, | ||
| isString = util.isString, | ||
| isNumber = util.isNumber, | ||
| identity = util.identity | ||
| module.exports = function(_r){ | ||
| var _ = _r._ || {} | ||
| _r._ = _ | ||
| _.iteratee = iteratee | ||
| _.matches = matches | ||
| _.property = property | ||
| } | ||
| function iteratee(value){ | ||
| var f | ||
| if(isNull(value)){ | ||
| f = identity | ||
| } else if(isFunction(value)){ | ||
| f = value | ||
| } else if(isKey(value)){ | ||
| f = property(value) | ||
| } else { | ||
| f = matches(value) | ||
| } | ||
| return f | ||
| } | ||
| function property(key){ | ||
| return function(value){ | ||
| return value[key] | ||
| } | ||
| } | ||
| function matches(attrs){ | ||
| var ps = pairs(attrs), | ||
| len = ps.length | ||
| return function(value){ | ||
| if(isNull(value)){ | ||
| return len === 0 | ||
| } | ||
| var i = 0, p, k, v | ||
| for(; i < len; i++){ | ||
| p = ps[i] | ||
| k = p[0] | ||
| v = p[1] | ||
| if(v !== value[k] || !(k in value)){ | ||
| return false | ||
| } | ||
| } | ||
| return true | ||
| } | ||
| } | ||
| function isNull(value){ | ||
| return value === void 0 || value === null | ||
| } | ||
| function isKey(value){ | ||
| return isString(value) || isNumber(value) | ||
| } | ||
| function pairs(value){ | ||
| var key, ps = [] | ||
| for(key in value){ | ||
| if(value.hasOwnProperty(key)){ | ||
| ps.push([key, value[key]]) | ||
| } | ||
| } | ||
| return ps | ||
| } |
+3
-5
| { | ||
| "name": "underarm", | ||
| "main": "build/underarm.min.js", | ||
| "version": "0.2.1", | ||
| "version": "0.6.0", | ||
| "homepage": "https://github.com/kevinbeaty/underarm", | ||
@@ -9,3 +9,3 @@ "authors": [ | ||
| ], | ||
| "description": "Async Reactive Transducers for JavaScript with Underscore API", | ||
| "description": "Transducers for JavaScript with Underscore API and Async extensions", | ||
| "moduleType": [ | ||
@@ -28,6 +28,4 @@ "amd", | ||
| "bower_components", | ||
| "test", | ||
| "tests", | ||
| "*-old" | ||
| "test" | ||
| ] | ||
| } |
+1
-1
@@ -1,2 +0,2 @@ | ||
| Copyright (C) 2012-2014 Kevin Beaty | ||
| Copyright (C) 2012-2015 Kevin Beaty | ||
@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
+11
-8
| { | ||
| "name": "underarm", | ||
| "version": "0.4.0", | ||
| "description": "Underscore Transducer meets Reactive Programming", | ||
| "version": "0.6.0", | ||
| "description": "Transducers for JavaScript with Underscore API and Async extensions", | ||
| "main": "underarm.js", | ||
@@ -16,15 +16,18 @@ "homepage": "https://github.com/kevinbeaty/underarm", | ||
| "underscore", | ||
| "transducer", | ||
| "reducer", | ||
| "reactive", | ||
| "rx", | ||
| "transducer", | ||
| "reducer" | ||
| "transduce" | ||
| ], | ||
| "author": "Kevin Beaty", | ||
| "license": "MIT", | ||
| "bugs": { | ||
| "url": "https://github.com/kevinbeaty/underarm/issues" | ||
| }, | ||
| "dependencies": { | ||
| "underscore-transducer": "~0.5.0", | ||
| "transduce": "~0.6.0", | ||
| "redispatch": "0.0.2", | ||
| "transduce-async": "~0.3.0", | ||
| "any-promise": "~0.1.0", | ||
| "lodash-node": "~3.3.0", | ||
| "transduce": "~0.6.0" | ||
| "lodash-node": "~3.3.0" | ||
| }, | ||
@@ -31,0 +34,0 @@ "devDependencies": { |
+577
-17
| # Underarm | ||
| [](http://travis-ci.org/kevinbeaty/underarm) | ||
| Use JavaScript with the familiar [Underscore.js][1] API with extra goodies like and [asynchronous (reactive) execution][2] and [lazy generators and callback processes][4]. | ||
| Use JavaScript transducers with the familiar [Underscore.js][1] API with extra goodies like [lazy generators and callback processes][4]. | ||
| Works with [any-promise][6] library (a pollyfill, es6-promise, promise, native-promise-only, bluebird, rsvp, when, q ... your choice) for asynchronous execution. | ||
| If you are not familiar with transducers, check out [Transducers Explained][3]. | ||
| Underarm is an extension to [underscore-transducer][5]. All methods there work with Underarm as well. Underarm allows any transducer to become asynchronous: Promises can be used and returned in `init`, `step` and `result`. If the transformation is not marked `async` behaves exactly the same as underscore-transducer. | ||
| Too much API for you? Just grab what you need from the [transduce][14] libraries, which underarm is based. | ||
| ## Install | ||
| Works with [any-promise][8] library (a pollyfill, es6-promise, promise, native-promise-only, bluebird, rsvp, when, q ... your choice) for asynchronous execution. Underarm allows any transducer to become asynchronous: Promises can be used and returned in `init`, `step` and `result`. | ||
| Install your Promise library preference before underarm and it will be auto detected and used. | ||
| ```bash | ||
| $ npm install promise # or es6-promise, bluebird, q, when, rsvp ... see any-promise | ||
| $ npm install underarm | ||
| $ bower install underarm | ||
| ``` | ||
| ### Browser | ||
@@ -22,10 +27,313 @@ Include an ES6 Promise Pollyfill. Then include the browser version of underarm. | ||
| ### Node.js | ||
| Library uses [any-promise][6] to allow choice of Promise library. | ||
| Structured to allow creation of custom builds by loading only desired libs. For example, see: | ||
| ```bash | ||
| $ npm install promise # or es6-promise, bluebird, q, when, rsvp ... see any-promise | ||
| $ npm install underarm | ||
| * [Base Development][20] | ||
| * [Base Minified][21] | ||
| Created by using `browserify` with [this loader][22]. | ||
| ### Transducers | ||
| First some helper functions and imports. | ||
| ```javascript | ||
| // import, mixin and helper functions | ||
| var _r = require('underarm'); | ||
| function isEven(x){ | ||
| return x % 2 !== 1; | ||
| } | ||
| function inc(x){ | ||
| return x+1; | ||
| } | ||
| // prints every result and input. Useful with tap | ||
| function printIt(result, input){ | ||
| console.log(input+' ['+result+']'); | ||
| } | ||
| var trans, result; | ||
| ``` | ||
| Chaining transducers is the same as function composition. Composed transducers are executed left to right. | ||
| ```javascript | ||
| result = _r.into([], _r.compose(_r.filter(isEven), _r.map(inc)), [1,2,3,4]); | ||
| // [ 3, 5 ] | ||
| // these are also the same | ||
| trans = _r().filter(isEven).map(inc).value(); | ||
| result = _r.into([], trans, [1,2,3,4, 5]); | ||
| result = _r().filter(isEven).map(inc).toArray([1,2,3,4,5]); | ||
| // [ 3, 5 ] | ||
| ``` | ||
| Like underscore, use `tap` to intercept intermediate results. Accepts current result and item just like the step function. The return value is ignored. | ||
| ```javascript | ||
| result = _r() | ||
| .filter(function(num) { return num % 2 == 0; }) | ||
| .tap(printIt) | ||
| .map(function(num) { return num * num }) | ||
| .toArray([1,2,3,200]); | ||
| // 2 [] | ||
| // 200 [4] | ||
| // [4, 40000 ] | ||
| ``` | ||
| Support for underscore collection functions. | ||
| ```javascript | ||
| result = _r().invoke('sort').toArray([[5, 1, 7], [3, 2, 1]]); | ||
| // [ [ 1, 5, 7 ], [ 1, 2, 3 ] ] | ||
| var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 40}]; | ||
| result = _r.into([], _r.pluck('name'), stooges); | ||
| // ['moe', 'larry', 'curly' ] | ||
| result = _r.into([], _r.where({age: 40}), stooges); | ||
| // [ { name: 'moe', age: 40 }, { name: 'curly', age: 40 } ] | ||
| result = _r.into([], _r.findWhere({age: 40}), stooges); | ||
| // [ { name: 'moe', age: 40 } ] | ||
| result = _r.into([], _r.every(isEven), [0, 2, 8, 4, 8]); | ||
| // [true] | ||
| result = _r.into([], _r.some(isEven), [1, 3, 7, 11, 9]); | ||
| // [false] | ||
| result = _r.into([], _r.contains(3), [1, 3, 7, 11, 9]); | ||
| // [true] | ||
| result = _r.into([], _r.find(isEven), [7, 8, 7, 11, 12]); | ||
| // [8] | ||
| result = _r.into([], _r.first(3), [1, 9, 13, 11, 9]); | ||
| // [1, 9, 13 ] | ||
| ``` | ||
| Transducers implemented | ||
| #### Base | ||
| Base Transducers mixing common functionality from supported [transduce][14] implementations. | ||
| ##### map(f) | ||
| Step all items after applying a mapping function to each item. Wraps mapping function with `_r.iteratee`. | ||
| Alias: collect | ||
| ##### filter(predicate) | ||
| Step all the items that pass a truth test. Wraps predicate with `_r.iteratee`. | ||
| Alias: select. | ||
| ##### remove(predicate) | ||
| Step all the items that fail a truth test. Wraps predicate with `_r.iteratee`. | ||
| Alias: reject | ||
| ##### take(n?) | ||
| Step the first item if `n` is undefined. Passing `n` will step the first N values in the array. | ||
| Resolves as single value if n is undefined. | ||
| Alias: first, head | ||
| ##### takeWhile(predicate) | ||
| Takes items until predicate returns false. Wraps predicate with `_r.iteratee`. | ||
| ##### drop(n?) | ||
| Steps everything but the first item if n is undefined. Passing an `n` will drop N values. | ||
| Alias: rest, tail | ||
| ##### dropWhile(predicate) | ||
| Drops items while predicate returns true. Wraps predicate with `_r.iteratee`. | ||
| ##### cat | ||
| Concatenating transducer. | ||
| NOTE: unlike libraries, cat should be called as a function. Use `_r.cat()` instead of `_r.cat` | ||
| ##### mapcat(f) | ||
| Composition of `_r.map(f)` and `_r.cat()`. Wraps mapping function with `_r.iteratee` | ||
| ##### partitionAll(n) | ||
| Partitions the source into arrays of size n. When transformer completes, the array will be stepped with any remaining items. | ||
| Alias: chunkAll | ||
| ##### partitionBy(f) | ||
| Partitions the source into sub arrays while the value of the function changes equality. Wrap partitioning function by `_r.iteratee`. | ||
| ##### compact() | ||
| Trim out all falsey values. | ||
| ##### invoke(method) | ||
| Invoke a method (with arguments) on every item. | ||
| ##### pluck(key) | ||
| Convenience version of a common use case of `map`: fetching a property. | ||
| ##### where(attrs) | ||
| Convenience version of a common use case of `filter`: selecting only objects containing specific `key:value` pairs. | ||
| #### Array | ||
| ##### forEach(iteratee) | ||
| Passes every item through unchanged, but after executing `callback(item, idx)`. Can be useful for "tapping into" composed transducer pipelines. The return value of the callback is ignored, item is passed unchanged. (See [transduce-stream][7] for a use case.) | ||
| Alias: each | ||
| ##### find(predicate) | ||
| Like filter, but terminates transducer pipeline with the result of the first item that passes the predicate test. Will always step either 0 (if not found) or 1 (if found) values. | ||
| Resolves as single value. | ||
| Alias: detect | ||
| ##### findWhere(attrs) | ||
| Convenience version of a common use case of `find`: getting the first object containing specific `key:value` pairs. Early termination when found. | ||
| Resolves as single value. | ||
| ##### every(predicate?) | ||
| Checks to see if every item passes the predicate test. Steps a single item `true` or `false`. Early termination on `false`. Wraps predicate in `_r.iteratee` | ||
| Resolves as single value. | ||
| Alias: all | ||
| ##### some(predicate?) | ||
| Checks to see if some item passes the predicate test. Steps a single item `true` or `false`. Early termination on `true`. Wraps predicate in `_r.iteratee` | ||
| Resolves as single value. | ||
| Alias: any | ||
| ##### contains(target) | ||
| Does the stream contain the target value (`target === item`)? Steps a single item `true` or `false`. Early termination on `true`. | ||
| Resolves as single value. | ||
| Alias: include | ||
| ##### push(...args) | ||
| Passes all items straight through until the result is requested. Once completed, steps every argument through the pipeline, before returning the result. This effectively pushes values on the end of the stream. | ||
| ##### unshift(...args) | ||
| Before stepping the first item, steps all arguments through the pipeline, then passes every item through unchanged. This effectively unshifts values onto the beginning of the stream. | ||
| ##### at(index) | ||
| Retrieves the value at the given index. Similar to indexing into an array. | ||
| Resolves as single value. | ||
| ##### slice(begin? end?) | ||
| Like array slice, but with transducers. Steps items between `begin` (inclusive) and `end` (exclusive). If either index is negative, indexes from end of transformation. If `end` is undefined, steps until result of transformation. If `begin` is undefined, begins at 0. | ||
| Note that if either index is negative, items will be buffered until completion. | ||
| ##### initial(n?) | ||
| Steps everything but the last entry. Passing `n` will step all values excluding the last N. | ||
| Note that no items will be sent and all items will be buffered until completion. | ||
| ##### last(n?) | ||
| Step the last element. Passing `n` will step the last N values. | ||
| Resolves as single value if `n` is undefined | ||
| Note that no items will be sent until completion. | ||
| ##### unique(isSorted?, iteratee?) | ||
| Produce a duplicate-free version of the transformation. If the transformation has already been sorted, you have the option of using an algorithm that maintains less state. If iteratee is passed, it will be wrapped with `_r.iteratee` and use return value for comparison. | ||
| Alias: uniq | ||
| #### Math | ||
| ##### min(f?) | ||
| Steps the max value on the result of the transformation. if `f` is provided, it is wrapped with `_r.iteratee` and called with each item and the return value is used to compare values. Otherwise, the items are compared as numbers. | ||
| Resolves as single value. | ||
| ##### max(f?) | ||
| Steps the max value on the result of the transformation. if `f` is provided, it is wrapped with `_r.iteratee` and called with each item and the return value is used to compare values. Otherwise, the items are compared as numbers. | ||
| Resolves as single value. | ||
| #### Strings | ||
| Strings are a sequence of characters, so you can transduce over those as well. Particularly useful with [transduce-stream][7]. | ||
| Functions that `split` over streams are treated as a substring, and splits across the entire transformation. This allows methods to work with chunks sent through streams. Methods that `split` over the String are processed lazily and as soon as possible: `lines`, `words` and `chars` will process a line/word/char as they are received, and buffer any intermediate chunks appropriately. | ||
| ##### split(separator, limit) | ||
| Works like `''.split` but splits across entire sequence of items. Accepts separator (String or RegExp) and limit of substrings to send. | ||
| ##### join(separator) | ||
| Buffers all items and joins results on transducer `result`. | ||
| Resolves as a single value. | ||
| ##### nonEmpty() | ||
| Only steps items that are non empty strings (`input.trim().length > 0`). | ||
| ##### lines(limit?) | ||
| Split chunks into lines and steps each line up to the optional limit. | ||
| ##### chars(limit?) | ||
| Split chunks into characters and steps each char up to the optional limit. | ||
| ##### words(delimiter?, limit?) | ||
| Split chunks into words and steps each word up to the optional limit. Can pass an optional delimiter to identify words, default on whitespace (`/\s+/`). | ||
| ### Chaining | ||
| Chaining is implicit when calling as a function `_r()`, and the source can be optionally passed as an argument to the function. When chaining, each of the transducers can be called as a builder similar to underscore. | ||
| ##### value() | ||
| Call on a chained transformation to sequence a wrapped value through the transformation and resolve as a value. The value returned is similar to underscore. Transducers that resolve as a single value are noted above. If a function does not resolve as a single value, resolves a a collection determined by `_r.empty(source)` (see below, normally an array). | ||
| ##### compose() | ||
| Call on chained transformation to compose all transducer functions in chain and return a transducer that can be used to pass to transduce functions. | ||
| Alias: transducer | ||
| ##### mixin() | ||
| Mixin custom transducer creating functions. Transducer creating functions will be called with arguments passed when chaining and should return a transducer. All transducers described above are mixed in. | ||
| ### Transduce functions | ||
| Adds functionality from [transduce][14] with default values from dispatched functions and chained transformations. | ||
| ##### toArray(xf?, from?) | ||
| Returns a new orray by iterating through`from` after running it through the optional transformation. | ||
| If called on a chained transformation, uses the composed transformation as `xf`. If `from` is not defined, uses the wrapped source when creating the chain, `_r(wrapped)`. | ||
| ##### into(to?, xf?, from?) | ||
| Returns a new collection appending all items into the empty collection `to` by passing all items from source collection `from` through the transformation `xf`. | ||
| Uses generic dispatch `_r.append` for reducing function. If the `from` collection is undefined, creates an empty collection using `_r.empty()`. If `xf` is a chained transformation, composes it. | ||
| Delegates to `_r.transduce(xf, _r.append, to, from)` if `xf is defined, otherwise `_r.reduce(_r.append, to, from)` if `xf` is undefined. | ||
| If called on a chained transformation, uses the composed transformation as `xf`. If `from` is not defined, uses the wrapped source when creating the chain, `_r(wrapped)`. If `to` is not defined, uses `_r.empty(from)` to create an empty value. | ||
| ##### transduce(xf?, f, init, coll?) | ||
| Transduce over a transformation using the installed transducers library, using chained transformation if chaining. If chaining and the source collection is not defined, uses wrapped source passed when creating the chain `_r(wrapped)`. Calls generic dispatch `_r.unwrap` with result before returning. | ||
| ##### reduce(f, init, coll?) | ||
| Reduces over a transformation using the installed transducers library. If the source `coll` is undefined, or null, creates an empty source by dispatching to `_r.empty(coll)`. | ||
| Alias: foldl, inject | ||
| ##### reduced | ||
| Ensures values are reduced to signal early termination when stepping through a transformation. Probably only useful if you want to mixin custom transducers. Use `_r.isReduced` to check if a value is wrapped as `reduced`. Use generic dispatch `_r.unwrap` to unwrap reduced values. | ||
| ### Async | ||
@@ -38,3 +346,3 @@ Uses [transduce-async][15] to support promises in transducer `init`, `step` and `result`. | ||
| ##### prototype.value() | ||
| Resolve value as [underscore-transducer][5] if not `async`. If chained transformation is `async` returns a promise for the value of the transformation | ||
| If chained transformation is `async` returns a promise for the value of the transformation | ||
@@ -48,3 +356,3 @@ ##### prototype.then(resolve, reject) | ||
| #### transduce(xf?, f, init, coll?) | ||
| Like a normal transduce when chained transformation is `async`. If `async`, `init` and `coll` can be a Promise and `xf` can be an async transducer. The value of `coll` can be anything that can be converted to an iterator using [transduce-protocol][16]. The return value is a Promise for the result of the transformation. | ||
| Like a normal transduce when chained transformation is `async`. If `async`, `init` and `coll` can be a Promise and `xf` can be an async transducer. The value of `coll` can be anything that can be converted to an iterator using [transduce][14]. The return value is a Promise for the result of the transformation. | ||
@@ -71,11 +379,260 @@ ##### into(to?, xf?, from?) | ||
| ### License | ||
| ### Iterators | ||
| Transduce, into, etc. accept generators or any iterator in addition to arrays. An iterator can either adapt the protocol or simply define a next function. | ||
| ```javascript | ||
| function* genNums(){ | ||
| yield 1; | ||
| yield 2; | ||
| yield 3; | ||
| yield 4; | ||
| } | ||
| result = _r.into([], _r.first(3), genNums()); | ||
| // [1, 2, 3 ] | ||
| ``` | ||
| ### Sequence generation | ||
| Generate will create an iterator that executes a callback. This can be used to generate potentially infinite sequences. | ||
| ```javascript | ||
| // Returns a function that generates the next fibonacci number | ||
| // every time it is called. Use with generators below | ||
| function fib(){ | ||
| var x=1, y=1; | ||
| return function(){ | ||
| var prev = x; | ||
| x = y; | ||
| y += prev; | ||
| return prev; | ||
| } | ||
| } | ||
| ``` | ||
| If not chaining, creates an iterator that can be used with transduce. If chaining, creates an iterator a wraps the result. Pass true as second argument optionally call function to init on each iteration (allows reuse). | ||
| ```javascript | ||
| // call on init to allow reuse | ||
| trans = _r().generate(fib, true).first(7); | ||
| result = trans.value(); | ||
| result = trans.value(); | ||
| ``` | ||
| ### Callback Processes | ||
| Transducers can be consumed by reduce, but since they are designed to be independent, we can use them in a variety of contexts that consume an input and produce a result, such as [CSP][3]. We can also create a process using a callback where each call advances a step in the process. These can be used as event handlers (like the [demo][4]). | ||
| ```javascript | ||
| var $demo = $('#demo3'), | ||
| coords = _r() | ||
| .where({type:'mousemove'}) | ||
| .map(function(e){return {x: e.clientX, y: e.clientY}}) | ||
| .map(function(p){return '('+p.x+', '+p.y+')'}) | ||
| .each(updateText) | ||
| .asCallback(), | ||
| click = _r() | ||
| .where({type:'click'}) | ||
| .each(updateCount) | ||
| .asCallback(), | ||
| events = _r() | ||
| .each(coords) | ||
| .each(click) | ||
| .asCallback(); | ||
| $demo.on('mousemove click', events); | ||
| function updateText(p){ | ||
| $demo.html(p); | ||
| } | ||
| function updateCount(e, idx){ | ||
| $demo.html('Click '+idx); | ||
| } | ||
| ``` | ||
| We are composing transducers. The previous examples are all using transducers behind the scenes. Method chaining is implicit and is composition, `_r.generate` uses an iterator and passes on to `transduce`. Even `asCallback` uses transducers but steps through the results using the argument of a callback, instead of reducing over the results. | ||
| ##### tap(interceptor) | ||
| Transduce also adds `tap`, which invokes interceptor with each result and item, and then steps through unchanged. The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. Executes interceptor with current result and item. | ||
| ### Node Async | ||
| If you are using Node.js, `asyncCallback` returns a callback that follows the standard convention of `fn(err, item)` and accepts a continuation that is called on completion or error. | ||
| ### Streams | ||
| You can transduce over Node.js Streams with [transduce-stream][7]. | ||
| ```javascript | ||
| // test.js | ||
| var _r = require('underarm'); | ||
| stream = require('transduce-stream'); | ||
| var transducer = _r() | ||
| .words() | ||
| .map(function(x){return (+x * +x)+ ' '}) | ||
| .uniq() | ||
| .take(4) | ||
| .push('\n') | ||
| .compose(); | ||
| process.stdin.resume(); | ||
| process.stdin.pipe(stream(transducer)).pipe(process.stdout); | ||
| ``` | ||
| Run this from the terminal to calculate a formatted sequence of the first 4 unique squared values. | ||
| ```bash | ||
| $ echo '33 27 33 444' | node test.js | ||
| 1089 729 197136 | ||
| $ node test.js << EOT | ||
| 12 32 | ||
| 33 33 | ||
| 33 43 | ||
| 12 33 12 | ||
| EOT | ||
| 144 1024 1089 1849 | ||
| ``` | ||
| ### Generic dispatch | ||
| Since input and output are separated the transducer transformation, transducers can be reduced, and sequences can be created over any object that supports the following methods. | ||
| ##### iterator(value) | ||
| Returns an iterator that has next function and returns `{value, done}`. Default looks for object with iterator Symbol (or `'@@iterator'`) | ||
| ##### iteratee(value) | ||
| Just like underscore, you can use "where style" objects and strings with functions that expect a mapping function or a predicate. By default, uses `_.iteratee` to match this behavior, but setup as a dispatched function to allow custom behavior. | ||
| ##### empty(value?) | ||
| Returns empty object of the same type as argument. Default returns `[]` if `_.isArray` or `undefined`, `{}` if `_.isObject` and an internal sentinel to ignore otherwise (used when not buffering in `asCallback` or chained `value` expects single value. | ||
| ##### append(result, item) | ||
| Accepts an item and optional key and appends the item to the object. By default, appends to arrays and objects by key and returns last item when used in `asCallback` or chained transducer with single `value`. | ||
| ##### wrap(value?) / unwrap(value) | ||
| When chaining transducers, the object passed to `_r(obj)` is dispatched to `_r.wrap`. By default, the object is not wrapped if it is defined, and wrapped with `_r.empty()` if not defined. When transducing over the sequence (with `value`, `into`, etc.) the object is then unwrapped with `_r.unwrap`. By default, unwrap calls `_r().value()` on chained transformations, extracts value from `_r.reduced` or simply returns the value. You can provide custom dispatchers for custom wrapped values. | ||
| #### Example | ||
| You can dispatch to custom objects by registering supporting dispatch functions. Say, for example, you love using [immutable][6] collections. | ||
| ```javascript | ||
| var _r = require('underarm'), | ||
| _ = require('underscore'), | ||
| Immutable = require('immutable'), | ||
| Vector = Immutable.Vector; | ||
| _r.iterator.register(function(obj){ | ||
| if(obj instanceof Vector){ | ||
| return obj.values(); | ||
| } | ||
| }); | ||
| _r.empty.register(function(obj){ | ||
| if(obj instanceof Vector){ | ||
| return Vector.empty(); | ||
| } | ||
| }); | ||
| _r.append.register(function(obj, item){ | ||
| if(obj instanceof Vector){ | ||
| return obj.push(item); | ||
| } | ||
| }); | ||
| function mult(x){ | ||
| return function(y){ | ||
| return x * y; | ||
| } | ||
| } | ||
| function isEven(x){ | ||
| return !(x % 2); | ||
| } | ||
| var vector = Vector(1,2,3,4); | ||
| // Vector [ 1, 2, 3, 4 ] | ||
| _r.sequence(vector); | ||
| // Vector [ 3, 6, 9, 12 ] | ||
| _r.sequence(_r.map(mult(3)), vector); | ||
| // Vector [ 7, 14, 21, 28 ] | ||
| _r(vector).map(mult(7)).sequence(); | ||
| // Vector [ 14, 28 ] | ||
| _r(vector).map(mult(7)).filter(isEven).sequence(); | ||
| // Vector [ 1, 2, 3, 4 ] | ||
| _r(vector).sequence(); | ||
| ``` | ||
| By default, `value` transduces into an empty array if multiple values are expected, and a single value if single value is expected to match the Underscore API. To override the behavior of multiple values, simply register a dispatch an empty for an undefined object (`value` calls `_r.empty()` which by default returns an array). | ||
| ```javascript | ||
| // [ 1, 2, 3, 4 ] | ||
| _r(vector).value(); | ||
| _r.empty.register(function(obj){ | ||
| if(_.isUndefined(obj)){ | ||
| return Vector.empty(); | ||
| } | ||
| }); | ||
| // Vector [ 1, 2, 3, 4 ] | ||
| _r(vector).value(); | ||
| ``` | ||
| #### Utils | ||
| Finally, adds utils from [transduce][14]. | ||
| ##### compose() | ||
| Simple function composition of arguments. Useful for composing (combining) transducers. | ||
| ##### iterable(value) | ||
| Returns the iterable for the parameter. Returns value if conforms to iterable protocol. Returns `undefined` if cannot return en iterable. | ||
| The return value will either conform to iterator protocol that can be invoked for iteration or will be undefined. | ||
| Supports anything that returns true for `isIterable` and converts arrays to iterables over each indexed item. Converts to functions to infinite iterables that always call function on next | ||
| ##### transformer(value) | ||
| Attempts to convert the parameter into a transformer. If cannot be converted, returns `undefined`. If defined, the return value will have `init`, `step`, `result` methods that can be used for transformation. Converts arrays (`arrayPush`), strings (`stringAppend`), objects (`objectMerge`), functions (wrap as reducing function) or anything that `isTransformer` into a transformer. | ||
| ##### protocols | ||
| Symbols (or strings that act as symbols) for `@@iterator` and [`@@transformer`][10] that you can use to configure your custom objects. | ||
| ##### identity(value) | ||
| Always returns value | ||
| ##### arrayPush(arr, item) | ||
| Array.push as a reducing function. Calls push and returns array; | ||
| ##### objectMerge(object, item) | ||
| Merges the item into the object. If `item` is an array of length 2, uses first (0 index) as the key and the second (1 index) as the value. Otherwise iterates over own properties of items and merges values with same keys into the result object. | ||
| ##### stringAppend(string, item) | ||
| Appends item onto result using `+`. | ||
| ##### is{Array, String, RegExp, Number, Undefined} | ||
| Predicates for object types | ||
| #### License | ||
| MIT | ||
| [1]: http://underscorejs.org/ | ||
| [2]: http://simplectic.com/projects/underarm/ | ||
| [3]: http://simplectic.com/blog/2014/transducers-explained-1/ | ||
| [4]: http://simplectic.com/projects/underscore-transducer/ | ||
| [5]: https://github.com/kevinbeaty/underscore-transducer | ||
| [6]: https://github.com/kevinbeaty/any-promise | ||
| [4]: http://simplectic.com/projects/underarm/ | ||
| [5]: http://clojure.org/transducers | ||
| [6]: https://github.com/facebook/immutable-js | ||
| [7]: https://github.com/transduce/transduce-stream | ||
| [8]: https://github.com/kevinbeaty/any-promise | ||
| [12]: https://raw.githubusercontent.com/kevinbeaty/underarm/master/build/underarm.js | ||
@@ -85,2 +642,5 @@ [13]: https://raw.githubusercontent.com/kevinbeaty/underarm/master/build/underarm.min.js | ||
| [15]: https://github.com/transduce/transduce-async | ||
| [16]: https://github.com/transduce/transduce-protocol | ||
| [18]: https://github.com/kevinbeaty/underarm | ||
| [20]: https://raw.githubusercontent.com/kevinbeaty/underarm/master/build/underarm.base.js | ||
| [21]: https://raw.githubusercontent.com/kevinbeaty/underarm/master/build/underarm.base.min.js | ||
| [22]: https://github.com/kevinbeaty/underarm/tree/master/underarm.base.js |
+4
-3
@@ -1,3 +0,4 @@ | ||
| module.exports = require('underscore-transducer/lib/load')([ | ||
| require('./lib/async')], | ||
| require('underscore-transducer/underscore-transducer.base')) | ||
| module.exports = require('./lib/load')([ | ||
| require('./lib/util'), | ||
| require('./lib/dispatch'), | ||
| require('./lib/transduce')]) |
+13
-4
@@ -1,5 +0,14 @@ | ||
| module.exports = require('underscore-transducer/lib/load')([ | ||
| require('./lib/lodash'), | ||
| module.exports = require('./lib/load')([ | ||
| require('./lib/util'), | ||
| require('./lib/util-async'), | ||
| require('./lib/dispatch'), | ||
| require('./lib/transduce'), | ||
| require('./lib/sequence'), | ||
| require('./lib/array'), | ||
| require('./lib/unique'), | ||
| require('./lib/push'), | ||
| require('./lib/iterator'), | ||
| require('./lib/math'), | ||
| require('./lib/string'), | ||
| require('./lib/async'), | ||
| require('./lib/sample')], | ||
| require('underscore-transducer')) | ||
| require('./lib/sample')]) |
| 'use strict' | ||
| module.exports = function(_r){ | ||
| var _ = _r._ || {} | ||
| _.debounce = require('lodash-node/compat/function/debounce') | ||
| _.throttle = require('lodash-node/compat/function/throttle') | ||
| } |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
58376
387.52%22
120%1066
363.48%1
-50%642
682.93%1
Infinity%+ Added
- Removed
- Removed