柯里化 (curry)

curry 的概念很简单:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

你可以一次性地调用 curry 函数,也可以每次只传一个参数分多次调用。

var add = function(x) {
  return function(y) {
    return x + y;
  };
};
var increment = add(1);
var addTen = add(10);
increment(2);
// 3
addTen(2);
// 12

这里我们定义了一个 add 函数,它接受一个参数并返回一个新的函数。调用 add 之后,返回的函数就通过闭包的方式记住了 add 的第一个参数。一次性地调用它实在是有点繁琐,好在我们可以使用一个特殊的 curry 帮助函数(helper function)使这类函数的定义和调用更加容易。

通过lodash

lodash/ramda 中提供了一个 curry 方法, 用于将函数进行柯里化

var curry = require('lodash').curry;
// =========== match ===========
var match = curry(function(what, str) {
  return str.match(what);
});
match(/\s+/g, "hello world"); // [ ' ' ]
match(/\s+/g)("hello world"); // [ ' ' ]
var hasSpaces = match(/\s+/g); // function(x) { return x.match(/\s+/g) }
hasSpaces("hello world"); // [ ' ' ]
hasSpaces("spaceless"); // null
// =========== replace ===========
var replace = curry(function(what, replacement, str) {
  return str.replace(what, replacement);
});
var noVowels = replace(/[aeiou]/ig); // function(replacement, x) { return x.replace(/[aeiou]/ig, replacement) }
var censored = noVowels("*"); // function(x) { return x.replace(/[aeiou]/ig, "*") }
censored("Chocolate Rain"); // 'Ch*c*l*t* R**n'
// =========== filter ===========
var filter = curry(function(f, ary) {
  return ary.filter(f);
});
filter(hasSpaces, ["tori_spelling", "tori amos"]); // ["tori amos"]
var findSpaces = filter(hasSpaces); // function(xs) { return xs.filter(function(x) { return x.match(/\s+/g) }) }
findSpaces(["tori_spelling", "tori amos"]); // ["tori amos"]
// =========== map ===========
var map = curry(function(f, ary) {
  return ary.map(f);
});

上面的代码中遵循的是一种简单,同时也非常重要的模式。即策略性地把要操作的数据(String, Array)放到最后一个参数里。

这里表明的是一种“预加载”函数的能力,通过传递一到两个参数调用函数,就能得到一个记住了这些参数的新函数。

偏函数

通过bind自身,可以创建偏函数:

function add(a, b){
  return a + b;
}
var addOne = add.bind(this, 1);
addOne(2); // 3

lodash 中提供了一个 partial 方法,也可以创建偏函数:

const _ = require('lodash')
function add(a, b){
  return a + b;
}
var addOne = _.partial(add, 1);
addOne(2); // 3

参考资料

MIT Licensed | Copyright © 2018-present 滇ICP备16006294号

Design by Quanzaiyu | Power by VuePress