This is a generalized curry function. It does normal currying plus a bit more.
As you would expect, the curried function supports sequential partial application. However, This 'curry' function also allows for non-sequential partial application. It also allows the currying of variable argument functions.
Curry function:
Code:
Function.freeArg = {
toString: function() {
return "[object FreeArg]";
}
};
function curry(f /*, n [, a] */) {
return f.curry(arguments[1], arguments[2]);
}
Function.prototype.curry = (function() {
var toString = function() {
return String(this.valueOf());
};
return function(/* n [, a] */) {
var f = this;
var a = arguments[1] || [];
var n = typeof arguments[0] == "number"
? arguments[0]
: f.length;
return function() {
if(!arguments.length)
return arguments.callee;
var p = a.slice();
var i = -1;
while(i = p.indexOf(Function.freeArg, i + 1), i != -1)
p[i] = p.shift.call(arguments);
p.push.apply(p, arguments);
if(n < 0) {
var g = f.curry(n, p);
g.valueOf = function() {
return f.apply(null, p);
};
g.toString = toString;
return g;
}
if(p.length < n || p.indexOf(Function.freeArg) != -1)
return f.curry(n, p);
return f.apply(null, p);
};
};
})();
if(!Array.prototype.indexOf)
Array.prototype.indexOf = function(v, i) {
var n = this.length;
if((i |= 0) < 0) {
i += n;
if(i < 0)
i = 0;
}
for(; i < n; ++i)
if(this[i] === v)
return i;
return -1;
};
With non-sequential partial application, supply Function.freeArg in the argument to be temporarily bypassed. In my example, I declare _ to equal Function.freeArg to give the code a more functional feel.
With variable arg currying (mandatory if you repeatedly do partial application, but otherwise not), when you curry the function, you need to specify the number of arguments to curry as a negative number, such as -1. Normally the curry function infers the number of arguments to curry as the default function argument length. In the case that you do supply the negative value length argument, any application of the returned function always return a function that always returns a function, etc. To get the value of the function, you need to force its value either explicitly or implicitly via the toString or valueOf methods of the function.
Example code:
Code:
var _ = Function.freeArg;
-------------------------------------
// a curried add function
var add = curry(function(x, y) {
return x + y;
});
var inc = add(1);
-------------------------------------
// a curried sub function
var sub = curry(function(x, y) {
return x - y;
});
var oneMinus = sub(1);
var dec = sub(_, 1);
-------------------------------------
// a variable argument average function
var average = curry(function() {
var sum = 0;
for(var i = 0; i < arguments.length; ++i) {
sum += arguments[i];
}
return sum / arguments.length;
}, -1); // note the -1 argument!
var avg_4_7_args = average(4, 7);
var avg_4_7_0_args = avg_4_7_args(0);
var avg_1_2_3_args = average(1)(2)(3);
-------------------------------------
var alert_x_y_z_w = function(x, y, z, w) {
alert([x, y, z, w].join('\n'));
}.curry(); // OO-style
var alert_1_y_2_w = alert_x_y_z_w(1, _, 2, _);
-------------------------------------
var x = 5;
alert(inc(x));
alert(oneMinus(x));
alert(dec(x));
alert(avg_4_7_args(1, 2, 3));
alert(avg_4_7_0_args(1,2)(3)(4,5,6));
alert(avg_1_2_3_args());
alert_1_y_2_w(3, 4);
The example code doesn't show much or explain much, but what it does demonstrate is the flexibility of how you can call the curried function. To understand what currying is, you can try:
- http://ianhenderson.org/currying_in_javascript.html
- http://www.google.com/search?hl=en&q...=Google+Search
In the short, a curried function allows you to pass one argument at a time to a function, and that will return a new function if there are arguments that you "still need to pass" into the function.
Last edited by Trinithis; 05-02-2008 at 03:51 AM..
I've seen this on the web, and wondered if it doesn't provide another example of how to use this thing. I wonder, though, is this really what Curry had in mind. As I read your links, 'currying' removes an argument, first or last, so using n-1 arguments. But this 'curry', if that's what it is, is useful because it gets the machine to do what one otherwise might have to do with multiple handlers or multi-dim objects. Here, you just send function for any object, and it works in its own 'space', almost like a 'class'. It doesn't know about other objects though to test for collision. Maybe it could?
The 'moveit' function is just an example, it could be any function at all obviously. Here, since the onclick is set, initially, onclick is fired again within moveit to keep the animation going.
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style>
</style>
</head>
<body>
<p><a id="runa" href="#">Run</a> <a id="runb" href="#">Jack</a> <a id="runc" href="#">Run</a><br>
<script>
function curry(scope, func) {
var s = scope, f = func, n = 2;
var args = Array.prototype.slice.call(arguments, n);
return (function () {
var o = s || this;
var allArgs = args.concat(Array.prototype.slice.call(arguments, 0));
return (f.apply(o, allArgs));
}
)
}
var ary = [ document.getElementById("runa"),
document.getElementById("runb"),
document.getElementById("runc") ];
function moveit(that, e){
that.style.marginLeft = that.style.marginLeft || "0px";
if (parseInt(that.style.marginLeft) <800){
that.style.marginLeft = parseInt(that.style.marginLeft) +10 +"px";
setTimeout(that.onclick,200);
}
}
for (var i in ary) {
ary[i].onclick = curry(ary[i], function(e) { moveit(this, e) });
}
</script>
</body>
</html>
What you have posted is not a curry function. It's actually partial application function. While they are closely related, they are not the same thing.
Partial application is simpler to understand. Partial application is where you supply some of the arguments to a function but not all of them. Then you get a new function that remembers those and asks for the remaining functions before execution.
In a sense, curring is a technique to enable automatic partial application. More formally, currying is a technique to turn a function into a function that accepts one and only one argument. In turn, when called, that function returns another function that accepts one and only one argument . . . and so on until the 'original' function is able to be executed.
Take for example, real number subtraction (call it f) in a math sense. f requires two inputs, both of which are real number. Then it returns another real number.
Note: R x R (same as R^2) is simply a pair of real numbers (x, y).
We say that f is a function from two real number to a real number.
That is in math notation . . .
Code:
f : R x R -> R
or more compactly . . .
Code:
f : R^2 -> R
So what this is saying is that f takes two real numbers for input and returns a real number.
In C++, this notation looks like:
Code:
real f(real, real)
In Haskell, this notation looks like:
Code:
f :: (Real, Real) -> Real
Well, when you curry f, call it f', you get:
Code:
f' : R -> (R -> R)
In C++, this might look something like:
Code:
realToReal f_prime(real)
In Haskell
Code:
f' :: Real -> (Real -> Real)
In all, curring a function creates a new function which allows you to feed an argument into it one at a time rather than all at once.
Hope this helps, though I'm not sure if I'm being too mathy.
I appreciate the clarification. I've been reading a number of pages now on this, and I see the difference. Frankly, I'd never heard of either until your thread. Lot to learn.
Oh, I just looked at your moveit code. Just so you know, you are doing too much with your "curry" (should have been named "partialApply") function. While what you did does work, the scope variable is intended to be used only when applied on a method with a specific object is in mind. If you have seen a Function.prototype.bind function, it is similar to that.
If you used a real curry function, such as mine, you could have written the code as one of the following:
Code:
ary[i].onclick = curry(moveit)(ary[i]);
ary[i].onclick = moveit.curry()(ary[i]);
// with mine you can save a little computation by doing it like:
ary[i].onclick = curry(moveit, null, [ary[i]]);
ary[i].onclick = moveit.curry(null, [ary[i]]);
What exactly is a "curry function", curry means to beat, bash, and thrash, to tan leather, to clean the coat of a horse, I am not seeking what that has exactly to do with a function?
There were links explaining it, above, and my own reference to a man's name.
I liked the closure it provides, especially that PAF as it was pointed out, so that 'the computer' handles each object, previous states, present states, etc. 'Set and forget'. No need for extra arrays or objects to track that for separate instances. It's done 'automatically'.