const pipeline = (...funcs) =>
val => funcs.reduce((a, b) => b(a), val)
const plus1 = a => a + 1
const mult2 = a => a * 2
const addThenMult = pipeline(plus1, mult2)
let r = addThenMult(5)
console.log(r)
看上去很简单的代码,但是结果却不是一眼能看得出来的。
真是写起来很简洁,读起来火葬场啊。
解析:
plus1和mult2都比较好理解,难点是pipeline这里。首先它是一个匿名函数,入参是多个函数组成的函数参数数组,返回的是 val => funcs.reduce((a, b) => b(a), val)这个匿名函数,代码中把这个匿名函数赋给了addThenMult,那么调用addThenMult时的传参5就对应val.
funcs.reduce((a, b) => b(a), val) 中的b(a)刚开始很让人疑惑,funcs是函数数组,给人的错觉是a和b都是函数,那么b(a)是函数嵌套?没见过这种写法啊。
其实并不是,如果你注意到reduce函数的第二个参数,就知道它是初始值,所以第一次循环时a是初始值val,b是函数plus1,运算结果是plus1(val),第二次循环时,a的值就变成了plus1(val),b函数是mult2,结果就是mul2(plus1(val))——最终实现的还是函数嵌套效果。
所以addThenMult(5)就等效于mul2(plus1(5))=(5+1)*2=12。
在WebStorm里对上面的代码进行ES6 to ES5转换,转换后的代码是:
"use strict";
var pipeline = function pipeline() {
for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
funcs[_key] = arguments[_key];
}
return function (val) {
return funcs.reduce(function (a, b) {
return b(a);
}, val);
};
};
var plus1 = function plus1(a) {
return a + 1;
};
var mult2 = function mult2(a) {
return a * 2;
};
var addThenMult = pipeline(plus1, mult2);
var r = addThenMult(5);
//# sourceMappingURL=test.js.map
你能看到结果是12吗?
换成Java的写法就是:
Function<Stream<Function<Integer, Integer>>, Function<Integer, Integer>>
pipline = funcs -> val -> funcs.reduce((a, b) -> b.compose(a)).get().apply(val);
Function<Integer, Integer> plus1 = a -> a + 1;
Function<Integer, Integer> mult2 = a -> a * 2;
Function<Integer, Integer> addThenMult = pipline.apply(Stream.of(plus1, mult2));
Integer r = addThenMult.apply(5);
参考:
网友评论