JavaScript: The Definitive Guide, Sixth Editio javaScript权威指南(第6版) pdf 文字版-文字版, javascript电子书, 和javascript 有关的电子书:

8.8.3 Partial Application of Functions

8.8.3 Partial Application of Functions


The bind() method of a function f ( §8.7.4 ) returns a new function that invokes f in a specified context and with a specified set of arguments. We say that it binds the function to an object and partially applies the arguments. The bind() method partially applies arguments on the left—that is, the arguments you pass to bind() are placed at the start of the argument list that is passed to the original function. But it is also possible to partially apply arguments on the right:

// A utility function to convert an array-like object (or suffix of it) // to a true array. Used below to convert arguments objects to real arrays. function array(a, n) { return Array.prototype.slice.call(a, n || 0); }

// The arguments to this function are passed on the left

function partialLeft(f /*, ...*/) { var args = arguments; // Save the outer arguments array return function() { // And return this function

var a = array(args, 1); // Start with the outer args from 1 on. a = a.concat(array(arguments)); // Then add all the inner arguments. return f.apply(this, a); // Then invoke f on that argument list.

}; }

// The arguments to this function are passed on the right

function partialRight(f /*, ...*/) { var args = arguments; // Save the outer arguments array return function() { // And return this function

var a = array(arguments); // Start with the inner arguments. a = a.concat(array(args,1)); // Then add the outer args from 1 on. return f.apply(this, a); // Then invoke f on that argument list.

}; }

// The arguments to this function serve as a template. Undefined values // in the argument list are filled in with values from the inner set. function partial(f /*, ... */) {

var args = arguments; // Save the outer arguments array

return function() { var a = array(args, 1); // Start with an array of outer args var i=0, j=0; // Loop through those args, filling in undefined values from inner for(; i < a.length; i++)

if (a[i] === undefined) a[i] = arguments[j++]; // Now append any remaining inner arguments a = a.concat(array(arguments, j)) return f.apply(this, a);

}; }

// Here is a function with three arguments var f = function(x,y,z) { return x * (y - z); }; // Notice how these three partial applications differ partialLeft(f, 2)(3,4) // => -2: Bind first argument: 2 * (3 - 4) partialRight(f, 2)(3,4) // => 6: Bind last argument: 3 * (4 - 2) partial(f, undefined, 2)(3,4) // => -6: Bind middle argument: 3 * (2 - 4)

These partial application functions allow us to easily define interesting functions out of functions we already have defined. Here are some examples:

var increment = partialLeft(sum, 1); var cuberoot = partialRight(Math.pow, 1/3); String.prototype.first = partial(String.prototype.charAt, 0); String.prototype.last = partial(String.prototype.substr, -1, 1);

8.8 Functional Programming | 195

Partial application becomes even more interesting when we combine it with other higher-order functions. Here, for example, is a way to define the not() function shown above using composition and partial application:

var not = partialLeft(compose, function(x) { return !x; }); var even = function(x) { return x % 2 === 0; }; var odd = not(even); var isNumber = not(isNaN)

We can also use composition and partial application to redo our mean and standard deviation calculations in extreme functional style:

var data = [1,1,3,5,5]; // Our data var sum = function(x,y) { return x+y; }; // Two elementary functions var product = function(x,y) { return x*y; }; var neg = partial(product, -1); // Define some others var square = partial(Math.pow, undefined, 2); var sqrt = partial(Math.pow, undefined, .5); var reciprocal = partial(Math.pow, undefined, -1);

// Now compute the mean and standard deviation. This is all function // invocations with no operators, and it starts to look like Lisp code! var mean = product(reduce(data, sum), reciprocal(data.length)); var stddev = sqrt(product(reduce(map(data,

compose(square, partial(sum, neg(mean)))), sum), reciprocal(sum(data.length,-1))));

欢迎转载,转载请注明来自一手册:http://yishouce.com/book/1/31373.html
友情链接It题库(ittiku.com)| 版权归yishouce.com所有| 友链等可联系 admin#yishouce.com|粤ICP备16001685号-1