Skip to content

Commit f00d310

Browse files
committed
Merge pull request chuanxshi#26 from kybernetikos/patch-1
Update function-patterns/currying.html
2 parents 5280097 + ba2d54e commit f00d310

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

function-patterns/currying.html

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,76 @@
101101
// reference
102102
// http://www.jspatterns.com/
103103
// http://shop.oreilly.com/product/9780596806767.do?sortby=publicationDate
104+
105+
// Here's a generic curry function (from kybernetikos):
106+
// It's slightly more complex than the common examples of currying (e.g. the one above), but that's because
107+
// the function can afterwards be called either in the normal way, or in the curried way.
108+
// If you call a 3 argument curried function with it, the returned function *is also curried*.
109+
// e.g. you can write func(arg1)(arg2)(arg3) or func(arg1, arg2, arg3) or func(arg1)(arg2, arg3) etc...
110+
111+
/* the curry procedure needs to know how many arguments are required before it should calculate the result */
112+
function curry(func, minArgs) {
113+
if (minArgs == undefined) {minArgs = 1;}
114+
115+
function funcWithArgsFrozen(frozenargs) {
116+
return function() {
117+
// could do an optmisation here - if called with no arguments
118+
// return exactly this function.
119+
var args = Array.prototype.slice.call(arguments);
120+
var newArgs = frozenargs.concat(args);
121+
if (newArgs.length >= minArgs) {
122+
return func.apply(this, newArgs);
123+
} else {
124+
return funcWithArgsFrozen(newArgs);
125+
}
126+
};
127+
};
128+
129+
return funcWithArgsFrozen([]);
130+
}
131+
132+
/* Here are some example uses - I use these with a functional immutable list structure implemented in js
133+
but they also work ok for normal higher order functions over arrays.
134+
*/
135+
136+
var plus = curry(function() {
137+
var result = 0;
138+
for (var i = 0; i < arguments.length; ++i) {
139+
result += arguments[i];
140+
}
141+
return result;
142+
}, 2);
143+
144+
/* Now you can call
145+
plus(3,2) // normal call
146+
plus(3) // partial application (returns a function that adds 3 to its argument)
147+
plus(3)(2) // complete application (returns 5)
148+
plus()(3)()()(2) // returns 5
149+
plus(3, 2, 4, 5) // the normal call can optionally take more than the minimum number of arguments
150+
plus(3)(2, 3, 5) // the last application can too.
151+
*/
152+
153+
var minus = curry(function(x) {
154+
var result = x;
155+
for (var i = 1; i < arguments.length; ++i) {
156+
result -= arguments[i];
157+
}
158+
return result;
159+
}, 2);
160+
161+
/* flip switches the order of the first two arguments on a function. It is curried itself and
162+
the function it returns is curried too. Particularly useful if you want a function that subtracts a number */
163+
164+
var flip = curry(function(func) {
165+
return curry(function(a, b) {
166+
return func(b, a);
167+
}, 2);
168+
});
169+
170+
/* for example
171+
minus(5) // returns a function that takes its argument away from 5
172+
flip(minus)(5) // returns a function that takes 5 away from its argument
173+
*/
104174
</script>
105175
</body>
106176
</html>

0 commit comments

Comments
 (0)