From 68476cd8900ce5f647b98d8b7708baf3983f2640 Mon Sep 17 00:00:00 2001 From: Dante Date: Tue, 3 Nov 2015 18:47:41 -0500 Subject: [PATCH 1/2] Added dependencies to the end of a stream --- lib/index.js | 4 +++- test/index.js | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index ff7a9bf..14f2f90 100644 --- a/lib/index.js +++ b/lib/index.js @@ -60,7 +60,8 @@ function updateStream(s) { return; } inStream = s; - var returnVal = s.fn(s, s.depsChanged); + s.fnArgs[1] = s.depsChanged; + var returnVal = s.fn.apply(s.fn, s.fnArgs); if (returnVal !== undefined) { s(returnVal); } @@ -190,6 +191,7 @@ function createDependentStream(deps, fn) { s.depsMet = false; s.depsChanged = fn.length > 1 ? [] : undefined; s.shouldUpdate = false; + s.fnArgs = [s, s.depsChanged].concat(s.deps); addListeners(deps, s); return s; } diff --git a/test/index.js b/test/index.js index a651d78..f4e4f3d 100644 --- a/test/index.js +++ b/test/index.js @@ -738,5 +738,22 @@ describe('stream', function() { [], [1, 3, 2], [2, 8, 7, 6], [3, 5, 4] ]); }); + it('should call dependent streams with dependencies', function() + { + var result = []; + var a = flyd.stream(); + var b = flyd.stream(0); + var dependent = flyd.stream([a, b], function(d, changed, a, b) + { + result.push(a()); + result.push(b()); + }); + a(1)(2); + b(3); + a(4); + assert.deepEqual(result, [ + 1, 0, 2, 0, 2, 3, 4, 3 + ]); + }) }); }); From 70d5b95a064d4cfc5bd655d2ad06e3461222d252 Mon Sep 17 00:00:00 2001 From: Dante Date: Wed, 4 Nov 2015 13:48:28 -0500 Subject: [PATCH 2/2] rebuilt flyd.js and updated with a better test. --- flyd.js | 218 +++++++++++++++++--------------------------------- test/index.js | 19 ++--- 2 files changed, 82 insertions(+), 155 deletions(-) diff --git a/flyd.js b/flyd.js index aa2acb6..97dfcd5 100644 --- a/flyd.js +++ b/flyd.js @@ -1,4 +1,4 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.flyd=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1 ? [] : undefined; s.shouldUpdate = false; + s.fnArgs = [s, s.depsChanged].concat(s.deps); addListeners(deps, s); return s; } @@ -287,85 +289,11 @@ module.exports = { immediate: immediate, }; -},{"ramda/src/curryN":4}],2:[function(require,module,exports){ -/** - * A special placeholder value used to specify "gaps" within curried functions, - * allowing partial application of any combination of arguments, - * regardless of their positions. - * - * If `g` is a curried ternary function and `_` is `R.__`, the following are equivalent: - * - * - `g(1, 2, 3)` - * - `g(_, 2, 3)(1)` - * - `g(_, _, 3)(1)(2)` - * - `g(_, _, 3)(1, 2)` - * - `g(_, 2, _)(1, 3)` - * - `g(_, 2)(1)(3)` - * - `g(_, 2)(1, 3)` - * - `g(_, 2)(_, 3)(1)` - * - * @constant - * @memberOf R - * @category Function - * @example - * - * var greet = R.replace('{name}', R.__, 'Hello, {name}!'); - * greet('Alice'); //=> 'Hello, Alice!' - */ -module.exports = {ramda: 'placeholder'}; - -},{}],3:[function(require,module,exports){ +},{"ramda/src/curryN":2}],2:[function(require,module,exports){ +var _arity = require('./internal/_arity'); +var _curry1 = require('./internal/_curry1'); var _curry2 = require('./internal/_curry2'); - - -/** - * Wraps a function of any arity (including nullary) in a function that accepts exactly `n` - * parameters. Unlike `nAry`, which passes only `n` arguments to the wrapped function, - * functions produced by `arity` will pass all provided arguments to the wrapped function. - * - * @func - * @memberOf R - * @sig (Number, (* -> *)) -> (* -> *) - * @category Function - * @param {Number} n The desired arity of the returned function. - * @param {Function} fn The function to wrap. - * @return {Function} A new function wrapping `fn`. The new function is - * guaranteed to be of arity `n`. - * @example - * - * var takesTwoArgs = function(a, b) { - * return [a, b]; - * }; - * takesTwoArgs.length; //=> 2 - * takesTwoArgs(1, 2); //=> [1, 2] - * - * var takesOneArg = R.arity(1, takesTwoArgs); - * takesOneArg.length; //=> 1 - * // All arguments are passed through to the wrapped function - * takesOneArg(1, 2); //=> [1, 2] - */ -module.exports = _curry2(function(n, fn) { - switch (n) { - case 0: return function() {return fn.apply(this, arguments);}; - case 1: return function(a0) {void a0; return fn.apply(this, arguments);}; - case 2: return function(a0, a1) {void a1; return fn.apply(this, arguments);}; - case 3: return function(a0, a1, a2) {void a2; return fn.apply(this, arguments);}; - case 4: return function(a0, a1, a2, a3) {void a3; return fn.apply(this, arguments);}; - case 5: return function(a0, a1, a2, a3, a4) {void a4; return fn.apply(this, arguments);}; - case 6: return function(a0, a1, a2, a3, a4, a5) {void a5; return fn.apply(this, arguments);}; - case 7: return function(a0, a1, a2, a3, a4, a5, a6) {void a6; return fn.apply(this, arguments);}; - case 8: return function(a0, a1, a2, a3, a4, a5, a6, a7) {void a7; return fn.apply(this, arguments);}; - case 9: return function(a0, a1, a2, a3, a4, a5, a6, a7, a8) {void a8; return fn.apply(this, arguments);}; - case 10: return function(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {void a9; return fn.apply(this, arguments);}; - default: throw new Error('First argument to arity must be a non-negative integer no greater than ten'); - } -}); - -},{"./internal/_curry2":6}],4:[function(require,module,exports){ -var __ = require('./__'); -var _curry2 = require('./internal/_curry2'); -var _slice = require('./internal/_slice'); -var arity = require('./arity'); +var _curryN = require('./internal/_curryN'); /** @@ -412,37 +340,32 @@ var arity = require('./arity'); * g(4); //=> 10 */ module.exports = _curry2(function curryN(length, fn) { - return arity(length, function() { - var n = arguments.length; - var shortfall = length - n; - var idx = n; - while (--idx >= 0) { - if (arguments[idx] === __) { - shortfall += 1; - } - } - if (shortfall <= 0) { - return fn.apply(this, arguments); - } else { - var initialArgs = _slice(arguments); - return curryN(shortfall, function() { - var currentArgs = _slice(arguments); - var combinedArgs = []; - var idx = -1; - while (++idx < n) { - var val = initialArgs[idx]; - combinedArgs[idx] = (val === __ ? currentArgs.shift() : val); - } - return fn.apply(this, combinedArgs.concat(currentArgs)); - }); - } - }); + if (length === 1) { + return _curry1(fn); + } + return _arity(length, _curryN(length, [], fn)); }); -},{"./__":2,"./arity":3,"./internal/_curry2":6,"./internal/_slice":7}],5:[function(require,module,exports){ -var __ = require('../__'); - +},{"./internal/_arity":3,"./internal/_curry1":4,"./internal/_curry2":5,"./internal/_curryN":6}],3:[function(require,module,exports){ +module.exports = function _arity(n, fn) { + // jshint unused:vars + switch (n) { + case 0: return function() { return fn.apply(this, arguments); }; + case 1: return function(a0) { return fn.apply(this, arguments); }; + case 2: return function(a0, a1) { return fn.apply(this, arguments); }; + case 3: return function(a0, a1, a2) { return fn.apply(this, arguments); }; + case 4: return function(a0, a1, a2, a3) { return fn.apply(this, arguments); }; + case 5: return function(a0, a1, a2, a3, a4) { return fn.apply(this, arguments); }; + case 6: return function(a0, a1, a2, a3, a4, a5) { return fn.apply(this, arguments); }; + case 7: return function(a0, a1, a2, a3, a4, a5, a6) { return fn.apply(this, arguments); }; + case 8: return function(a0, a1, a2, a3, a4, a5, a6, a7) { return fn.apply(this, arguments); }; + case 9: return function(a0, a1, a2, a3, a4, a5, a6, a7, a8) { return fn.apply(this, arguments); }; + case 10: return function(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) { return fn.apply(this, arguments); }; + default: throw new Error('First argument to _arity must be a non-negative integer no greater than ten'); + } +}; +},{}],4:[function(require,module,exports){ /** * Optimized internal two-arity curry function. * @@ -455,16 +378,15 @@ module.exports = function _curry1(fn) { return function f1(a) { if (arguments.length === 0) { return f1; - } else if (a === __) { + } else if (a != null && a['@@functional/placeholder'] === true) { return f1; } else { - return fn(a); + return fn.apply(this, arguments); } }; }; -},{"../__":2}],6:[function(require,module,exports){ -var __ = require('../__'); +},{}],5:[function(require,module,exports){ var _curry1 = require('./_curry1'); @@ -481,15 +403,16 @@ module.exports = function _curry2(fn) { var n = arguments.length; if (n === 0) { return f2; - } else if (n === 1 && a === __) { + } else if (n === 1 && a != null && a['@@functional/placeholder'] === true) { return f2; } else if (n === 1) { return _curry1(function(b) { return fn(a, b); }); - } else if (n === 2 && a === __ && b === __) { + } else if (n === 2 && a != null && a['@@functional/placeholder'] === true && + b != null && b['@@functional/placeholder'] === true) { return f2; - } else if (n === 2 && a === __) { + } else if (n === 2 && a != null && a['@@functional/placeholder'] === true) { return _curry1(function(a) { return fn(a, b); }); - } else if (n === 2 && b === __) { + } else if (n === 2 && b != null && b['@@functional/placeholder'] === true) { return _curry1(function(b) { return fn(a, b); }); } else { return fn(a, b); @@ -497,38 +420,45 @@ module.exports = function _curry2(fn) { }; }; -},{"../__":2,"./_curry1":5}],7:[function(require,module,exports){ +},{"./_curry1":4}],6:[function(require,module,exports){ +var _arity = require('./_arity'); + + /** - * An optimized, private array `slice` implementation. + * Internal curryN function. * * @private - * @param {Arguments|Array} args The array or arguments object to consider. - * @param {Number} [from=0] The array index to slice from, inclusive. - * @param {Number} [to=args.length] The array index to slice to, exclusive. - * @return {Array} A new, sliced array. - * @example - * - * _slice([1, 2, 3, 4, 5], 1, 3); //=> [2, 3] - * - * var firstThreeArgs = function(a, b, c, d) { - * return _slice(arguments, 0, 3); - * }; - * firstThreeArgs(1, 2, 3, 4); //=> [1, 2, 3] + * @category Function + * @param {Number} length The arity of the curried function. + * @return {array} An array of arguments received thus far. + * @param {Function} fn The function to curry. */ -module.exports = function _slice(args, from, to) { - switch (arguments.length) { - case 1: return _slice(args, 0, args.length); - case 2: return _slice(args, from, args.length); - default: - var list = []; - var idx = -1; - var len = Math.max(0, Math.min(args.length, to) - from); - while (++idx < len) { - list[idx] = args[from + idx]; +module.exports = function _curryN(length, received, fn) { + return function() { + var combined = []; + var argsIdx = 0; + var left = length; + var combinedIdx = 0; + while (combinedIdx < received.length || argsIdx < arguments.length) { + var result; + if (combinedIdx < received.length && + (received[combinedIdx] == null || + received[combinedIdx]['@@functional/placeholder'] !== true || + argsIdx >= arguments.length)) { + result = received[combinedIdx]; + } else { + result = arguments[argsIdx]; + argsIdx += 1; } - return list; - } + combined[combinedIdx] = result; + if (result == null || result['@@functional/placeholder'] !== true) { + left -= 1; + } + combinedIdx += 1; + } + return left <= 0 ? fn.apply(this, combined) : _arity(left, _curryN(length, combined, fn)); + }; }; -},{}]},{},[1])(1) +},{"./_arity":3}]},{},[1])(1) }); \ No newline at end of file diff --git a/test/index.js b/test/index.js index f4e4f3d..28f1796 100644 --- a/test/index.js +++ b/test/index.js @@ -740,20 +740,17 @@ describe('stream', function() { }); it('should call dependent streams with dependencies', function() { - var result = []; var a = flyd.stream(); var b = flyd.stream(0); - var dependent = flyd.stream([a, b], function(d, changed, a, b) - { - result.push(a()); - result.push(b()); - }); - a(1)(2); - b(3); - a(4); - assert.deepEqual(result, [ + var collect = function(self, changed, x, y){ return (self() || []).concat([x(), y()]); }; + + var history = flyd.stream([a, b], collect); + a(1)(2); // [1, 0, 2, 0] + b(3); // [1, 0, 2, 0, 2, 3] + a(4); // [1, 0, 2, 0, 2, 3, 4, 3] + assert.deepEqual(history(), [ 1, 0, 2, 0, 2, 3, 4, 3 ]); - }) + }); }); });