This repository has been archived by the owner on Nov 12, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 19
/
curry.js
97 lines (82 loc) · 3.74 KB
/
curry.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
var slice = Array.prototype.slice;
var toArray = function(a){ return slice.call(a) }
var tail = function(a){ return slice.call(a, 1) }
// fn, [value] -> fn
//-- create a curried function, incorporating any number of
//-- pre-existing arguments (e.g. if you're further currying a function).
var createFn = function(fn, args, totalArity){
var remainingArity = totalArity - args.length;
switch (remainingArity) {
case 0: return function(){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 1: return function(a){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 2: return function(a,b){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 3: return function(a,b,c){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 4: return function(a,b,c,d){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 5: return function(a,b,c,d,e){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 6: return function(a,b,c,d,e,f){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 7: return function(a,b,c,d,e,f,g){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 8: return function(a,b,c,d,e,f,g,h){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 9: return function(a,b,c,d,e,f,g,h,i){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
case 10: return function(a,b,c,d,e,f,g,h,i,j){ return processInvocation(fn, concatArgs(args, arguments), totalArity) };
default: return createEvalFn(fn, args, remainingArity);
}
}
// [value], arguments -> [value]
//-- concat new arguments onto old arguments array
var concatArgs = function(args1, args2){
return args1.concat(toArray(args2));
}
// fn, [value], int -> fn
//-- create a function of the correct arity by the use of eval,
//-- so that curry can handle functions of any arity
var createEvalFn = function(fn, args, arity){
var argList = makeArgList(arity);
//-- hack for IE's faulty eval parsing -- http://stackoverflow.com/a/6807726
var fnStr = 'false||' +
'function(' + argList + '){ return processInvocation(fn, concatArgs(args, arguments)); }';
return eval(fnStr);
}
var makeArgList = function(len){
var a = [];
for ( var i = 0; i < len; i += 1 ) a.push('a' + i.toString());
return a.join(',');
}
var trimArrLength = function(arr, length){
if ( arr.length > length ) return arr.slice(0, length);
else return arr;
}
// fn, [value] -> value
//-- handle a function being invoked.
//-- if the arg list is long enough, the function will be called
//-- otherwise, a new curried version is created.
var processInvocation = function(fn, argsArr, totalArity){
argsArr = trimArrLength(argsArr, totalArity);
if ( argsArr.length === totalArity ) return fn.apply(null, argsArr);
return createFn(fn, argsArr, totalArity);
}
// fn -> fn
//-- curries a function! <3
var curry = function(fn){
return createFn(fn, [], fn.length);
}
// num, fn -> fn
//-- curries a function to a certain arity! <33
curry.to = curry(function(arity, fn){
return createFn(fn, [], arity);
});
// num, fn -> fn
//-- adapts a function in the context-first style
//-- to a curried version. <3333
curry.adaptTo = curry(function(num, fn){
return curry.to(num, function(context){
var args = tail(arguments).concat(context);
return fn.apply(this, args);
});
})
// fn -> fn
//-- adapts a function in the context-first style to
//-- a curried version. <333
curry.adapt = function(fn){
return curry.adaptTo(fn.length, fn)
}
module.exports = curry;