Created
October 9, 2013 08:09
-
-
Save dannycallaghan/6897882 to your computer and use it in GitHub Desktop.
Currying / Partial Application From 'JavaScript Patterns' (O'Reilly) by Stoyan Stefanov.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Currying */ | |
// Currying is making JavaScript functions understand and handle partial application | |
// A non-curried add functions | |
var add = function ( x, y ) { | |
return x + y; | |
}; | |
// A curried add function | |
function add ( x, y ) { | |
if ( typeof y === "undefined" ) { | |
// partial application: | |
// if there's no second argument, the closure closes around the first argument, | |
// storing it's value, and returns a function ready to receive a second argument | |
return function ( y ) { | |
return x + y; | |
}; | |
} | |
// full application: | |
// we have all the necessary arguments, so we just use a full application (non-curried) add function | |
return x + y; | |
} | |
add( 3, 4 ); // 7 | |
add( 5 )( 4 ); // 9 | |
var addSix = add( 1 ); | |
console.log( typeof addSix ); // function | |
var result = addSix( 4 ) // 10 | |
// A general purpose curry function | |
function curry ( fn ) { | |
var slice = Array.prototype.slice, | |
stored_args = slice.call( arguments, 1 ); | |
return function () { | |
var new_args = slice.call( arguments ), | |
args = stored_args.concat( new_args ); | |
return fn.apply( null, args ); | |
}; | |
} | |
// A non-curried add functions | |
var add = function ( x, y ) { | |
return x + y; | |
}; | |
// curry a function to get a new function | |
var newadd = curry( add, 5 ); | |
newadd( 4 ); // 9 | |
// another option -- call the new function directly | |
curry( add, 6 )( 7 ); // 13 | |
// Works with any number of params | |
// a normal function | |
function add( a, b, c, d, e ) { | |
return a + b + c + d + e; | |
} | |
curry( add, 1, 2, 3 )( 5, 5 ); // 16 | |
// two-step currying | |
var addOne = curry( add, 1 ); | |
addOne( 10, 10, 10, 10 ); // 41 | |
var addSix = curry( addOne, 2, 3 ); | |
addSix( 5, 5 ); // 16 | |
// When to Use Currying | |
// When you find yourself calling the same function and passing mostly the same param- eters, then the function is | |
// probably a good candidate for currying. You can create a new function dynamically by partially applying a set of | |
// arguments to your function. The new function will keep the repeated parameters stored (so you don’t have to pass | |
// them every time) and will use them to pre-fill the full list of arguments that the original function expects. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment