Comparing version 0.2.1 to 0.3.0
@@ -16,3 +16,3 @@ /*global exports:true,define:false*/ | ||
'use strict'; | ||
var slice = [].slice; | ||
var slice = Array.prototype.slice; | ||
var RIGHT = 'unshift'; | ||
@@ -31,12 +31,14 @@ | ||
* @param {boolean} [seal=true] Whether to prevent args beyond the len. | ||
* @param {Array.<*>} [held=[]] | ||
* @return {function} A function that executes fn once it's been passed all its arguments. | ||
*/ | ||
return function (fn, len, forceOne, seal) { | ||
return function currier(fn, len, forceOne, seal, held) { | ||
seal = seal !== false; | ||
len = !!len ? len : fn.length; | ||
var held = []; | ||
return function curried(args) { | ||
curried._fn = fn; | ||
args = slice.call(arguments, 0); | ||
held = held || []; | ||
var captured = function curried(args) { | ||
var next = null; | ||
var old = held.slice(); | ||
args = slice.call(arguments); | ||
if (forceOne) { | ||
@@ -51,6 +53,9 @@ held[adder](args[0]); | ||
if (held.length < len) { | ||
return curried; | ||
next = currier(fn, len, !!forceOne, !!seal, held); | ||
held = old; | ||
return next; | ||
} else { | ||
if (seal) { | ||
held.splice(len); | ||
// Clear off the beginning if it's a right | ||
held = !reverse ? held.slice(0, len) : held.slice(held.length - len); | ||
} | ||
@@ -60,2 +65,4 @@ return fn.apply(this, held); | ||
}; | ||
captured._fn = fn; | ||
return captured; | ||
}; | ||
@@ -62,0 +69,0 @@ }; |
/** | ||
* @license | ||
* curry-d 0.2.0 https://github.com/jnewman/curry-d/blob/master/LICENSE.txt | ||
* Build time: 2013-07-13A01:07:40 | ||
* curry-d 0.3.0 https://github.com/jnewman/curry-d/blob/master/LICENSE.txt | ||
* Build time: 2013-07-13P14:07:18 | ||
*/ | ||
;!function(a,b){"function"==typeof define&&define.amd?define(["exports"],b):"object"==typeof exports?b(exports):b(a)}(this,function(a){"use strict";var b=[].slice,c="unshift",d=function(a){var d=a===c;return function(c,e,f,g){g=g!==!1,e=e?e:c.length;var h=[];return function i(j){return i._fn=c,j=b.call(arguments,0),f?h[a](j[0]):h[a].apply(h,d?j.reverse():j),h.length<e?i:(g&&h.splice(e),c.apply(this,h))}}};a.curry=d("push"),a.curryRight=a.curry.r=d(c),a.uncurry=a.curry.un=function(a){return a._fn||a}}); | ||
;!function(a,b){"function"==typeof define&&define.amd?define(["exports"],b):"object"==typeof exports?b(exports):b(a)}(this,function(a){"use strict";var b=Array.prototype.slice,c="unshift",d=function(a){var d=a===c;return function e(c,f,g,h,i){h=h!==!1,f=f?f:c.length,i=i||[];var j=function(j){var k=null,l=i.slice();return j=b.call(arguments),g?i[a](j[0]):i[a].apply(i,d?j.reverse():j),i.length<f?(k=e(c,f,!!g,!!h,i),i=l,k):(h&&(i=d?i.slice(i.length-f):i.slice(0,f)),c.apply(this,i))};return j._fn=c,j}};a.curry=d("push"),a.curryRight=a.curry.r=d(c),a.uncurry=a.curry.un=function(a){return a._fn||a}}); |
{ | ||
"name": "curry-d", | ||
"version": "0.2.1", | ||
"description": "An optimized version of curry. UMD compatible for widespread use", | ||
"version": "0.3.0", | ||
"description": "Curry and curryRight at arbitrary depth, then uncurry, if you want.", | ||
"author": "Joshua Newman <joshua.l.newman@gmail.com>", | ||
@@ -6,0 +6,0 @@ "keywords": [ |
# curry-d | ||
An efficient implementation of curry. Using a dispatcher, gets a little more than 20% speed increase | ||
over traditional approach while still adding lots of sugar.[1](http://jsperf.com/compare-curry-functions) | ||
A curry that uses a dispatcher to achieve arbitrary curry length w/ solid performance<sup>[3](http://jsperf.com/compare-curry-functions/3)</sup>. | ||
## Usage | ||
### Node | ||
Install as usual: | ||
npm install curry-d | ||
Functions are props of exports | ||
var bint = require('curry-d').curryRight(parseInt)(2); | ||
bint('101010'); // 42 | ||
### RequireJS | ||
Add the path to curry-d, then require as usual: | ||
define(function () { | ||
var bint = require('curry-d').curryRight(parseInt)(2); | ||
bint('101010'); // 42 | ||
}); | ||
### Globally in the browser | ||
var bint = curryRight(parseInt)(2); | ||
bint('101010'); // 42 | ||
## Functions | ||
This module exports three functions: curry, curryRight, and uncurry. | ||
@@ -25,8 +51,8 @@ | ||
var add = function () { | ||
var sum = function () { | ||
return require('lodash').reduce(arguments, function (total, n) {return total + n;}); | ||
}; | ||
var curried = curry(add)(40); // undefined | ||
var curried = curry(add, 2)(40); // a function | ||
var curried = curry(sum)(40); // undefined | ||
var curried = curry(sum, 2)(40); // a function | ||
curried(2); // 42 | ||
@@ -36,15 +62,15 @@ | ||
curry(add, 2)(40, 2); // 42 | ||
curry(sum, 2)(40, 2); // 42 | ||
Unless you want to force a single argument per call (handy w/ e.g., _.forEach): | ||
curry(add, 2, true)(40, 99)(2); // 42 | ||
curry(sum, 2, true)(40, 99)(2); // 42 | ||
However, you cannot overflow your arguments: | ||
curry(add, 2)(40, 2, 99); // 42 | ||
curry(sum, 2)(40, 2, 99); // 42 | ||
Unless you really want to: | ||
curry(add, null, null, false)(40, 2, 99); // 141 | ||
curry(sum, null, null, false)(40, 2, 99); // 141 | ||
@@ -71,2 +97,2 @@ ### curryRight | ||
More to come. | ||
@@ -16,3 +16,3 @@ /*global exports:true,define:false*/ | ||
'use strict'; | ||
var slice = [].slice; | ||
var slice = Array.prototype.slice; | ||
var RIGHT = 'unshift'; | ||
@@ -31,12 +31,14 @@ | ||
* @param {boolean} [seal=true] Whether to prevent args beyond the len. | ||
* @param {Array.<*>} [held=[]] | ||
* @return {function} A function that executes fn once it's been passed all its arguments. | ||
*/ | ||
return function (fn, len, forceOne, seal) { | ||
return function currier(fn, len, forceOne, seal, held) { | ||
seal = seal !== false; | ||
len = !!len ? len : fn.length; | ||
var held = []; | ||
return function curried(args) { | ||
curried._fn = fn; | ||
args = slice.call(arguments, 0); | ||
held = held || []; | ||
var captured = function curried(args) { | ||
var next = null; | ||
var old = held.slice(); | ||
args = slice.call(arguments); | ||
if (forceOne) { | ||
@@ -51,6 +53,9 @@ held[adder](args[0]); | ||
if (held.length < len) { | ||
return curried; | ||
next = currier(fn, len, !!forceOne, !!seal, held); | ||
held = old; | ||
return next; | ||
} else { | ||
if (seal) { | ||
held.splice(len); | ||
// Clear off the beginning if it's a right | ||
held = !reverse ? held.slice(0, len) : held.slice(held.length - len); | ||
} | ||
@@ -60,2 +65,4 @@ return fn.apply(this, held); | ||
}; | ||
captured._fn = fn; | ||
return captured; | ||
}; | ||
@@ -62,0 +69,0 @@ }; |
@@ -9,3 +9,3 @@ define(function (require) { | ||
require('./curry-d'); | ||
exports.test(expect, _, curryD); | ||
exports.test('AMD in browser', expect, _, curryD); | ||
}); |
@@ -9,3 +9,3 @@ (function () { | ||
require('./curry-d').test(expect, _, curryD); | ||
require('./curry-d').test('Require in Node', expect, _, curryD); | ||
})(); |
@@ -1,123 +0,210 @@ | ||
/*jshint evil:true,maxstatements:1000*/ | ||
/*jshint evil:true,maxstatements:10000*/ | ||
exports = typeof exports === 'undefined' ? {} : exports; | ||
exports.test = function (expect, _, curryD) { | ||
var curry = curryD.curry; | ||
var curryRight = curry.r; | ||
var uncurry = curry.un; | ||
exports.test = function (contextDescription, expect, _, curryD) { | ||
describe(contextDescription, function () { | ||
var curry = curryD.curry; | ||
var curryRight = curry.r; | ||
var uncurry = curry.un; | ||
var fns = null; | ||
beforeEach(function () { | ||
fns = { | ||
add2: function (a, b) { | ||
return a + b; | ||
}, | ||
add3: function (a, b, c) { | ||
return a + b + c; | ||
}, | ||
add20: function () { | ||
var sum = 0; | ||
for (var args = _.toArray(arguments); args.length > 0;) { | ||
sum += args.pop(); | ||
var fns = null; | ||
beforeEach(function () { | ||
fns = { | ||
add2: function (a, b) { | ||
return a + b; | ||
}, | ||
add3: function (a, b, c) { | ||
return a + b + c; | ||
}, | ||
sum: function () { | ||
return _.reduce(arguments, function (total, n) { | ||
return total + n; | ||
}); | ||
}, | ||
div5: function (a, b, c, d, e) { | ||
return a / b / c / d / e; | ||
}, | ||
wideRange: function (last) { | ||
return _.range(1, last + 1); | ||
} | ||
return sum; | ||
}, | ||
div5: function (a, b, c, d, e) { | ||
return a / b / c / d / e; | ||
}, | ||
mkNums: function (size) { | ||
var ns = []; | ||
for (var i = 1; i <= size; ++i) { | ||
ns.push(i); | ||
}; | ||
}); | ||
afterEach(function () { | ||
fns = null; | ||
}); | ||
var assertNumericCurriedByLength = function (currier, toCurry, len, total, fudge) { | ||
var curried = currier(toCurry); | ||
var oneShort = _.reduce(fns.wideRange(len - 1), function (c, num) { | ||
var ced = c(num); | ||
expect(ced).to.be.a('function'); | ||
return ced; | ||
}, curried); | ||
var result = oneShort(len); | ||
expect(result).to.be.a('number'); | ||
expect(result).to.be.closeTo(total, fudge || 0); | ||
}; | ||
var verifyFnLength = function (currier, forward) { | ||
it('returns a function until it reaches its length', function () { | ||
assertNumericCurriedByLength(currier, fns.add2, 2, 3); | ||
assertNumericCurriedByLength(currier, fns.add3, 3, 6); | ||
var nums = fns.wideRange(5); | ||
if (forward === false) { | ||
nums.reverse(); | ||
} | ||
return ns; | ||
} | ||
assertNumericCurriedByLength(currier, fns.div5, 5, eval(nums.join('/')), 0.001); | ||
}); | ||
}; | ||
}); | ||
afterEach(function () { | ||
fns = null; | ||
}); | ||
var assertNumericCurriedByForce = function (currier, toCurry, len, total, fudge) { | ||
return assertNumericCurriedByLength( | ||
_.partialRight(currier, len), | ||
toCurry, | ||
len, | ||
total, | ||
fudge | ||
); | ||
}; | ||
var assertNumericCurriedByLength = function (currier, toCurry, len, total, fudge) { | ||
var curried = currier(toCurry); | ||
var verifyForcedLength = function (currier, forward) { | ||
it('returns a function until it reaches forced size', function () { | ||
assertNumericCurriedByForce(currier, fns.add2, 2, 3); | ||
assertNumericCurriedByForce(currier, fns.add3, 3, 6); | ||
assertNumericCurriedByForce(currier, fns.sum, 20, 210); | ||
var oneShort = _.reduce(fns.mkNums(len - 1), function (c, num) { | ||
var ced = c(num); | ||
expect(ced).to.be.a('function'); | ||
return ced; | ||
}, curried); | ||
var nums = fns.wideRange(5); | ||
if (forward === false) { | ||
nums.reverse(); | ||
} | ||
var result = oneShort(len); | ||
expect(result).to.be.a('number'); | ||
expect(result).to.closeTo(total, fudge || 0); | ||
}; | ||
assertNumericCurriedByForce(currier, fns.div5, 5, eval(nums.join('/')), 0.001); | ||
}); | ||
}; | ||
var verifyFnLength = function (currier, forward) { | ||
it('returns a function until it reaches its length', function () { | ||
assertNumericCurriedByLength(currier, fns.add2, 2, 3); | ||
assertNumericCurriedByLength(currier, fns.add3, 3, 6); | ||
var verifyAllowsMultiple = function (currier) { | ||
it('allows extra arguments', function () { | ||
var curried = currier(fns.sum, 11); | ||
var nums = fns.mkNums(5); | ||
if (forward === false) { | ||
nums.reverse(); | ||
} | ||
assertNumericCurriedByLength(currier, fns.div5, 5, eval(nums.join('/')), 0.001); | ||
}); | ||
}; | ||
var oneShort = _.reduce(fns.wideRange(5), function (c, n) { | ||
var result = c(n, 1); | ||
expect(result).to.be.a('function'); | ||
return result; | ||
}, curried); | ||
var assertNumericCurriedByForce = function (currier, toCurry, len, total, fudge) { | ||
return assertNumericCurriedByLength( | ||
_.partialRight(currier, len), | ||
toCurry, | ||
len, | ||
total, | ||
fudge | ||
); | ||
}; | ||
expect(oneShort(1)).to.equal(21); | ||
}); | ||
}; | ||
var verifryForcedLength = function (currier, forward) { | ||
it('returns a function until it reaches forced size', function () { | ||
assertNumericCurriedByForce(currier, fns.add2, 2, 3); | ||
assertNumericCurriedByForce(currier, fns.add3, 3, 6); | ||
assertNumericCurriedByForce(currier, fns.add20, 20, 210); | ||
var verifyForcesSingle = function (currier) { | ||
it('goes one-by-one if forceOne', function () { | ||
var curried = _.partialRight(currier, null, true, true)(fns.add3); | ||
var nums = fns.mkNums(5); | ||
if (forward === false) { | ||
nums.reverse(); | ||
} | ||
var oneShort = _.reduce(fns.wideRange(2), function (c, n) { | ||
var result = c(n, 99, 114); | ||
expect(result).to.be.a('function'); | ||
return result; | ||
}, curried); | ||
assertNumericCurriedByForce(currier, fns.div5, 5, eval(nums.join('/')), 0.001); | ||
}); | ||
}; | ||
expect(oneShort(3)).to.equal(6); | ||
}); | ||
}; | ||
describe('curry', function () { | ||
verifyFnLength(curry); | ||
verifryForcedLength(curry); | ||
}); | ||
var verifyPreventsArgOverflow = function (currier) { | ||
it('stops taking arguments when the length is filled', function () { | ||
var curried = currier(fns.sum, 11); | ||
describe('curry right', function () { | ||
verifyFnLength(curryRight, false); | ||
verifryForcedLength(curryRight, false); | ||
}); | ||
var oneShort = _.reduce(fns.wideRange(5), function (c, n) { | ||
var result = c(n, 1); | ||
expect(result).to.be.a('function'); | ||
return result; | ||
}, curried); | ||
expect(oneShort(1, 999, 141, 1)).to.equal(21); | ||
}); | ||
}; | ||
describe('uncurry', function () { | ||
var checkAdd2 = function (currier) { | ||
expect(uncurry(currier(fns.add2)(99))(42, 42)).to.equal(84); | ||
var verifyCanForceOverflow = function (currier) { | ||
it('allows more arguments than its length', function () { | ||
var curried = _.partialRight(currier, null, false)(fns.sum, 11); | ||
var oneShort = _.reduce(fns.wideRange(5), function (c, n) { | ||
var result = c(n, 1); | ||
expect(result).to.be.a('function'); | ||
return result; | ||
}, curried); | ||
expect(oneShort(1, 20, 1)).to.equal(42); | ||
}); | ||
}; | ||
var checkAdd20 = function (currier) { | ||
expect(uncurry(currier(fns.add20, 20)(99)).apply(null, fns.mkNums(20))).to.equal(210); | ||
var verifyStatelessness = function (currier) { | ||
it('original curried function is not affected by arguments being passed', function () { | ||
var sumFive = currier(fns.sum, 5); | ||
var sumFour = sumFive(10); | ||
expect(sumFive(1,1,1,1,1)).to.equal(5); | ||
expect(sumFour(1,1,1,1)).to.equal(14); | ||
}); | ||
}; | ||
it('can be uncurry', function () { | ||
checkAdd2(curry); | ||
checkAdd20(curry); | ||
describe('curry', function () { | ||
verifyFnLength(curry); | ||
verifyForcedLength(curry); | ||
verifyAllowsMultiple(curry); | ||
verifyForcesSingle(curry); | ||
verifyPreventsArgOverflow(curry); | ||
verifyCanForceOverflow(curry); | ||
verifyStatelessness(curry); | ||
}); | ||
it('can be uncurryRight', function () { | ||
checkAdd2(curryRight); | ||
checkAdd20(curryRight); | ||
describe('curry right', function () { | ||
verifyFnLength(curryRight, false); | ||
verifyForcedLength(curryRight, false); | ||
verifyAllowsMultiple(curryRight); | ||
verifyForcesSingle(curryRight); | ||
verifyPreventsArgOverflow(curryRight); | ||
verifyCanForceOverflow(curryRight); | ||
verifyStatelessness(curryRight); | ||
it('can make bInt', function () { | ||
var bint = curryRight(parseInt)(2); | ||
expect(bint('101010')).to.equal(42); | ||
expect(bint('101010')).to.equal(42); | ||
}); | ||
}); | ||
describe('uncurry', function () { | ||
var checkAdd2 = function (currier) { | ||
expect(uncurry(currier(fns.add2)(99))(42, 42)).to.equal(84); | ||
}; | ||
var checkAdd20 = function (currier) { | ||
expect(uncurry(currier(fns.sum, 20)(99)).apply(null, fns.wideRange(20))).to.equal(210); | ||
}; | ||
it('gives back the original function', function () { | ||
expect(uncurry(curry(fns.sum))).to.equal(fns.sum); | ||
}); | ||
it('can be uncurry', function () { | ||
checkAdd2(curry); | ||
checkAdd20(curry); | ||
}); | ||
it('can be uncurryRight', function () { | ||
checkAdd2(curryRight); | ||
checkAdd20(curryRight); | ||
}); | ||
it('noops when the function is not curried', function () { | ||
expect(uncurry(fns.sum)).to.equal(fns.sum); | ||
}); | ||
}); | ||
}); | ||
}; |
(function (global) { | ||
var TESTS = [ | ||
'test/curry-d-amd' | ||
'test/curry-d-amd', | ||
'test/curry-d-global' | ||
]; | ||
@@ -5,0 +6,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23493
15
440
96