定义
函数组合又称 “饲养函数”。
是若干个纯函数、是若干个纯函数、、柯里化函数组合成一个新的函数、形成数据传递、并实现一种有序执行的效果。
定义一个函数compose用于处理函数的组合。
例子
基础版
只能组合两个函数
// 字符串转大写
function toUpperCase(str){
return str.toUpperCase();
}
// 增加感叹号
function exclaim(str){
return str + '!';
}
function compose(f, g){
return function(x){
return f(g(x)); //左倾 自右向左依次执行
}
}
// x是通过f, g之间的“管道”传输值
var f = compose(exclaim, toUpperCase);
console.log(f('hello')); //HELLO!
增强版
借助arguments
就能够组合多个函数
function toUpperCase(str){
return str.toUpperCase();
}
function exclaim(str){
return str + '!';
}
function split(arr){
return arr.split('');
}
function reverse(str){
return str.reverse();
}
function join(str){
return str.join('-');
}
function compose(){
var args = Array.prototype.slice.call(arguments), // 把arguments转为数组
len = args.length - 1;
return function(x){
var res = args[len](x);
while(len --){
res = args[len](res);
}
return res;
}
}
// 执行的方向是由右至左依次执行
var f = compose(join, reverse, splite, exclaim, toUpperCase);
console.log(f('hello')); // !-O-L-L-E-H
最终方案
使用reduceRight也能做到compose
function compose(){
return (x) => [].slice.call(arguments).reduceRight((res, cb) => cb(res), x);
}
结合律 Associativity
在组合函数的参数中,再进行分组,函数的分组组合和原来的组合所得出的结果是一样的。
与数字中的结合律表现是一致的。
var f = compose(join, reverse, split);
var f2 = compose(compose(join, reverse), split);
var f3 = compose(join, compose(reverse, split));
console.log(f('hello')); //o-l-l-e-h
console.log(f2('hello')); //o-l-l-e-h
console.log(f3('hello')); //o-l-l-e-h
point-free
一种编程风格,我们可以把数据处理的过程定义与数据无关的合成运算,不需要用到代表数据的哪个参数
只需要把运算步骤合成到一起,在使用这种模式之前需要定义一些辅助的基本运算函数。
- 不需要指明处理的数据
- 只需要合成运算过程
- 需要定义一些辅助的基本运算函数
Love means never having to say you’re sorry. Excuse me.
Pointfree style means never having to say your data.