Partially applying a function is a, particularly, interesting technique in which you can pre-fill-in arguments to a function before it is ever executed. In effect, partially applying a function returns a new function which you can call. This is best understood through an example:
String.prototype.csv = String.prototype.split.partial(/,\s*/); var results = "John, Resig, Boston".csv(); alert( (results[1] == "Resig") + " The text values were split properly" );
In the above case we’ve taken a common function – a String’s .split()
method – and have pre-filled-in the regular expression upon which to split. The result is a new function, .csv()
that we can call at any point to convert a list of comma-separated values into an array. Filling in the first couple arguments of a function (and returning a new function) is typically called currying. With that in mind, let’s look at how currying is, roughly, implemented in the Prototype library:
Function.prototype.curry = function() { var fn = this, args = Array.prototype.slice.call(arguments); return function() { return fn.apply(this, args.concat( Array.prototype.slice.call(arguments))); }; };
This is a good case of using a closure to remember state. In this case we want to remember the arguments that were pre-filled-in (args
) and transfer them to the newly-constructed function. This new function will have the filled-in arguments and the new arguments
concat’d together and passed in. The result is a method that allows us to fill in arguments, giving us a new function that we can use.
Now, this style of partial application is perfectly useful, but we can do better. What if we wanted to fill in any missing argument from a given function – not just the first ones. Implementations of this style of partial application have existed in other languages but Oliver Steele was one of the first to demonstrate it with his Functional.js library. Let’s take a look at a possible implementation:
Function.prototype.partial = function(){ var fn = this, args = Array.prototype.slice.call(arguments); return function(){ var arg = 0; for ( var i = 0; i < args.length && arg < arguments.length; i++ ) if ( args[i] === undefined ) args[i] = arguments[arg++]; return fn.apply(this, args); }; };[/js] This implementation is fundamentally similar to the <code>.curry()</code> method, but has a couple important differences. Notably, when called, the user can specify arguments that will be filled in later by specifying <code>undefined</code>, for it. To accommodate this we have to increase the ability of our arguments-merging technique. Effectively, we have to loop through the arguments that are passed in and look for the appropriate gaps, filling in the missing pieces that were specified. We already had the example of constructing a string splitting function, above, but let's look at some other ways in which this new functionality could be used. To start we could construct a function that's able to be easily delayed: [js] var delay = setTimeout.partial(undefined, 10); delay(function(){ alert( "A call to this function will be temporarily delayed." ); });
This means that we now have a new function, named delay
, which we can pass another function in to, at any time, to have it be called asynchronously (after 10 milliseconds).
We could, also create a simple function for binding events:
var bindClick = document.body.addEventListener .partial("click", undefined, false); bindClick(function(){ alert( "Click event bound via curried function." ); });
This technique could be used to construct simple helper methods for event binding in a library. The result would be a simpler API where the end-user wouldn’t be inconvenienced by unnecessary function arguments, reducing them to a single function call with the partial application.
In the end we’ve used closures to easily, and simply, reduce the complexity of some code, easily demonstrating some of the power that functional JavaScript programming has.
This is an excerpt from my work-in-progress book: Secrets of the JavaScript Ninja. To be released Fall 2008.
jaceju (February 14, 2008 at 4:21 am)
It does not work with IE6. @_@
Jörn Zaefferer (February 14, 2008 at 8:05 am)
I like the book title! Looking forward to it.
I wrote a partial String formatting helper some time ago:
jQuery.format = function(source, params) {
if ( arguments.length == 1 )
return function() {
var args = jQuery.makeArray(arguments);
args.unshift(source);
return jQuery.format.apply( this, args );
};
if ( arguments.length > 2 && params.constructor != Array ) {
params = jQuery.makeArray(arguments).slice(1);
}
if ( params.constructor != Array ) {
params = [ params ];
}
jQuery.each(params, function(i, n) {
source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
});
return source;
};
Worth noting is that you can pass an array as the second argument, or just list as many arguments as you like, both works.
Its heavily used in the validation plugin for specifying messages with parameters, eg. you often see {somefield: String.format(“Please provide more {0}”) }
Function borrowed from here..
Aaron (February 14, 2008 at 8:30 am)
Awesome! I love it. Made my week.
Christophe Grand (February 14, 2008 at 8:37 am)
In javascript it happens quite often that one wants to both partially apply a function and to bind this to a given object. (This-binding and defining a partial function are the same: this is a glorified first argument.)
That’s why I ended up defining a bindPartial method and coded curry, partial and bind using it.
Frederick Polgardy (February 14, 2008 at 8:50 am)
Cool technique for supporting out-of-order parameters! I never thought of that. Just last week I happened to write a post on currying in JavaScript; what are the chances?
FYI, I’m sure you knew this, but Prototype 1.6 provides a .delay() method on Function.prototype, which does exactly what you did above.
Marius (February 14, 2008 at 9:39 am)
Why not create a new function instead?
String.prototype.csv = function(){
return this.split(/,+s*/);
}
var results = "John, Resig, Boston".csv();
alert( (results[1] == "Resig") + " The text values were split properly" );
timothy (February 14, 2008 at 10:07 am)
Cool. Dan Webb covers partial functions in “The Art & Science of Javascript.” But I didn’t know about Steele’s Functional.js.
Dinoboff (February 14, 2008 at 10:19 am)
@marius: with partial and curry, you don’t have to repeat yourself; instead of:
setTimeout.partial(function(){/*do something*/}, 10);
setTimeout.partial(function(){/*do something else*/}, 10);
…
you’ve got:
var delay = setTimeout.partial(undefined, 10);
delay(function(){/*do something*/});
delay(function(){/*do something else*/});
John Resig (February 14, 2008 at 10:48 am)
@jaceju: I assume you’re referring to the fact that I use addEventListener as an example – that is correct, Internet Explorer doesn’t have addEventListener, so it’ll fail. Or that Internet Explorer doesn’t provide Function.prototype methods on native functions (like alert, setTimeout, etc.). That is true. I’ll make a note of that.
@Frederick Polgardy: Yep! That’s where I got the inspiration from. In this book I’ve been covering large portions of jQuery and Prototype, along with some parts of base2 – all libraries that I really like.
@Marius: Sure, you absolutely could – and in some cases that would probably be preferable. This is just a demonstration of what can be done with closures and partial functions.
Peter Michaux (February 14, 2008 at 10:54 am)
“Filling in the first couple arguments of a function (and returning a new function) is typically called currying.”
Brendan Eich will have your head. He had mine for referring to this as “currying”.
John Resig (February 14, 2008 at 11:16 am)
@Peter: *shrug* This definition is good enough for me: “Intuitively, currying says ‘if you fix some arguments, you get a function of the remaining arguments’.”
Dean Edwards (February 14, 2008 at 12:36 pm)
Was this post triggered by the code I sent you or just coincidence? :-)
Either way, very timely and a good read. Maybe
undefined
is better than Oliver’s “_” placeholder? Need to think about that.John Resig (February 14, 2008 at 1:20 pm)
@Dean: A little bit of both! ;-) But yeah, I’ve been planning on this for my book, for a while but had forgotten about Oliver’s particular technique – thanks for pushing me towards it, again! I definitely like some of the ways that you’re using it in base2 – you need to push your latest code live so that I can write about it more!
As far as using ‘_’ goes, I think
undefined
is probably a better, generic, strategy – considering that other libraries (or the user) could define an actual value for _, causing the use to go haywire. That being said, it’s definitely trivial for a user to do:var _;
to get that functionality in their own code.henrah (February 14, 2008 at 1:21 pm)
@John and Dean:
I don’t think
undefined
is a good placeholder for parameters; there are many plausible situations where you might want to explicitly passundefined
as a value, or you mnight simply be referring to a variable that hadn’t been initialized yet, in a way that makes sense in terms of your program logic. In either case, the sample code tests supplied arguments againstundefined
using==
instead of===
, so even explicit uses ofnull
will be treated as placeholders rather than actual values.I don’t think using “_” in the global scope makes sense as a placeholder constant, but something like
PLACE_HOLDER
does.Dean Edwards (February 14, 2008 at 2:32 pm)
@henrah – “PLACE_HOLDER”? Mmm. A tad verbose. I’ve been thinking of using three “_” characters. It’s a bit more readable:
var addClickEvent = addEvent.partial(_, "click", false);
versus:
var addClickEvent = addEvent.partial(___, "click", false);
I agree that
undefined
might be a real value that’s why I don’t use this is in base2.Reggie Drake (February 14, 2008 at 2:35 pm)
To harp on a bit more on the use of undefined to mark ’empty spots’ in the call — comparing to undefined with == will also match null, and there definitely are cases where you geniunely want to partially apply something to null or undefined. I’d recommend defining an object used purely for its identity, like ‘var __ = {};’. Now you can apply functions to everything you like, and check for placeholders with ‘== __’, which only returns true for this specific object. Plus you get a cool-looking placeholder symbol! (Unless, of course, some other code or library uses __. Know of any that do?)
John Resig (February 14, 2008 at 3:10 pm)
@henrah, Dean, and Reggie: Good catch on the == vs. ===. I just tweaked the code, above.
Although, as far as being concerned about legitimately wanting to pass in an ‘undefined’ value – I think that would happen just about as often as someone accidentally defining the same placeholder variable as you (not to mention that you now have an extra variable polluting the global scope). It seems like it’s a wash, either way, and should probably just be left up to the developer.
Oliver Steele (February 14, 2008 at 5:51 pm)
Nicely done!
I used ‘_’ because it’s used in math, and I move back and forth a lot between code and math. Languages such as Haskell and Scala use it for similar (not quite identical) purposes, so it also helps if you’re moving among JavaScript and those languages.
A potential problem with using undefined as the placeholder is that the most common(?) js error is the unexpected undefined — from using an uninitialized variable, or mistyping a property name, or forgetting a return, etc. — and using undefined as a special value makes this even harder to find, in the case where an (intended) non-placeholder values mistakenly ends up undefined. For example, a binder-maker such as function makeBinder(options) {return document.body.addEventListener.partial(options.nam, undefined, false)} [sic] will return a 2-ary function, since options.name is undefined.
Dean Edwards (February 14, 2008 at 8:56 pm)
OK Oliver you’ve convinced me. I’m going to stick with “_” in base2. BTW, I really like Functional.js. I learned a lot from reading the source code. Functional and jQuery are my favourite JavaScript libraries (apart from base2 of course ;-)).
Frederick Polgardy (February 15, 2008 at 9:43 am)
I think it’s a correctness vs. conciseness trade-off. If you’re willing to pass in something like Partial.PLACEHOLDER, then you can easily make that refer to an inaccessible object defined in a closure, and as long as you’re testing with ===, you’ll have an unambiguous placeholder. If you want to use _, you’ll have to settle for the possibility that it’ll get blown over by someone.
Oliver Steele (February 15, 2008 at 2:03 pm)
@Dean: Thanks, that’s high praise! You might also be interested in http://osteele.com/sources/javascript/sequentially/. It’s not as mainstream, but it’s fun, if you’re the kind of person who finds that kind of thing fun :-)
@Frederick: You’re right about the risk of _ and name collisions, of course. In Functionally, I use Functional._, but then define [global.]_ as a synonym. This way you can use Functional._ without risk of collisions, but _ if you know you aren’t re-binding it. This is similar to how jQuery uses jQuery as the authoritative variable name, but defines $ as a synonym.
anonymous (April 6, 2008 at 7:24 pm)
Regarding “currying”, Wikipedia is wrong, as it sometimes is. This is a common misconception about what currying is.
See http://lambda-the-ultimate.org/node/2266 (this is linked from the Wikipedia entry).
The following may be helpful (code is Haskell but should be self-explanatory).
A function that adds two numbers (it takes 1 argument, and that argument is a pair of numbers):
add (x, y) = x + y
An equivalent function in curried form (it now takes 2 arguments):
add1 x y = x + y
In Haskell, add1 could be defined as:
add1 = curry add
Partial application, which is what you are talking about here, would be defining something like:
plus_ten = add1 10
In this case, we are actually applying add1 to one argument (of its two arguments), which results in a function that accepts one argument (and adds 10 to that argument). This is not currying, which would be converting the function from accepting (x, y) as a single argument to accepting x and y as two arguments.