Function Programming - 柯里化(curry)
看到一篇非常不错的文章,这里分享给大家:http://www.jianshu.com/p/fa3568087881。
首先,柯里化的定义:你可以只透过部分的参数呼叫一个function,它会回传一个function 去处理剩下的参数。
我们从最简单的栗子开始:
var add = function(a) { return function(b) { return a + b; } } var addTen = add(10); addTen(5); // 15 同时,我们还可以这样调用: add(10)(5); //15
上述add函数是柯里化之后的函数,一般我们会如下定义add函数:
var add = function(a, b) { return a + b; }
一般的定义有什么问题呢,参数可能不小心多了,那多余的参数就会被忽略,也有可能传参传少了,那么函数执行会发生错误;而柯里化如果传部分参数只会返回要处理剩下参数的函数,make sense?
当然我们有工具使我们的函数柯里化,这里我们举例用lodash的https://lodash.com/docs/4.17.4#curry:
var add = _.curry(function(a, b) { return a + b; })
var addTen = add(10); addTen(5); // 15 同时,柯里化也接受传多个参数: add(10)(5); //15
我们再稍微深入理解一下:
var object = [{id: 1, name: 'test'}, {id: 2, name: 'test2'}, {id: 3, name: 'test3'}]; var getIds = object.map(o => (o.id));
上述代码明显是取objec里面各个id;这有个什么问题呢?我们没有办法重用getIds这个函数,因为每次想拿到id,都得进行一次map和取id的操作,我们再改进下这个函数:
var objects = [{id: 1, name: 'test'}, {id: 2, name: 'test2'}, {id: 3, name: 'test3'}]; var getId = (object) => (object.id); var getIds = objects.map(getId); //解释下为啥这里可以不用参数直接可以调用getId,因为fp(Function Programming)中函数是一等公民,function(a) {return getId(a);} 与 getId是等价的;
这样的,我们抽出去里getId这个函数,但是依然不能完全重用,因为每次还要进行一次map操作,再一次改进:
var objects = [{id: 1, name: 'test'}, {id: 2, name: 'test2'}, {id: 3, name: 'test3'}]; var getId = (object) => (object.id); var getIds = _.curry((objects) => objects.map(getId)); getIds(objects); //[1,2,3]
这个时候我们就用到里柯里化,但是依然不够好,因为如果我想拿到每个object的name呢,这个方法就做不到,我们就再一次改进看看:
var objects = [{id: 1, name: 'test'}, {id: 2, name: 'test2'}, {id: 3, name: 'test3'}]; var getValues = _.curry((objects, key) => objects.map((object) => (object[key]))); getValues(objects, 'name')
这样的话,我们就能取任何key的值了,只需要传入objects和key即可。
var objects = [{id: 1, name: 'test'}, {id: 2, name: 'test2'}, {id: 3, name: 'test3'}];
var getId = _.curry((property, object) => (object[property]));
var map = _.curry((fn, objects) => objects.map(fn));
var getValues = map(getId('id')); getValues(objects); 由于我们对key值进行的操作可能不一样,所以我们可以传一个函数;
这就是我们所介绍的curry啦,欢迎各位留言,提反馈!