Daily-Question
Daily-Question copied to clipboard
【Q181】如何实现 compose 函数,进行函数合成
实现一个 compose 函数,进行函数合成,比如 redux 中的 compose,react 高阶组件连续调用时的 compose
const add10 = x => x + 10
const mul10 = x => x * 10
const add100 = x => x + 100
// (10 + 100) * 10 + 10 = 1110
compose(add10, mul10, add100)(10)
function compose() {
let fns = [...arguments];
return function() {
let args = [...arguments];
let result = fns.reduce((ret, fn) => {
ret = fn.apply(this, ret);
return Array.isArray(ret) ? ret : [ret];
}, args);
return result;
}
}
let toUpperCase = (x) => x.toUpperCase();
let exclaim = (x) => x + '!';
let shout = compose(toUpperCase,exclaim);
let str = shout('hello world');
console.log(str);
第一次试着写,简单查了一下compose是什么意思,竟然拼凑出来了。请各位指正。 :smile:
看到一种新实现
function compose(...fns) {
fns.reduce( (a, b) => (...args) => a(b(...args)));
}
const compose = (...fns) => (...params) => fns.reduce((prev, current) => current(prev), ...params);
实现一个从右向左(right to left)计算的组合函数:
const compose = (...fns) =>
// 注意 f、g 的位置,如果实现从左到右计算,则置换顺序
fns.reduce((f, g) => (...args) => f(g(...args)))
跑一个示例
const add5 = x => x + 5
const multiply = (x) => x * 10
const multiply10AndAdd5 = compose(
add5,
multiply
)
multiply10AndAdd5(10) // 105
在 Redux
中广泛使用了 compose
函数,其中的实现如下
export default function compose(...funcs: Function[]) {
if (funcs.length === 0) {
// infer the argument type so it is usable in inference down the line
return <T>(arg: T) => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args: any) => a(b(...args)))
}
@nieyao params 应该置后,测试示例时没有通过
@nieyao params 应该置后,测试示例时没有通过
确实,忘了compose是从右往左执行的,那加个reverse 好了。 const compose = (...fns) => (...params) => fns.reverse().reduce((prev, current) => current(prev), ...params) 或者用reduceRight const compose = (...fns) => (...params) => fns.reduceRight((prev, current) => current(prev), ...params)
function compose(...fn) {
return (...args) => fn.reverse().slice(1).reduce((acc, cur) => cur(acc), fn[0](...args))
}
这种方式更优雅
const compose = (...fns) =>
fns.reduceRight(
(prev, next) =>
(...args) =>
prev(next(...args))
);
之前看了koa的compose实现,先入为主了,感觉写的没上面的优雅,不过能过用例:
function compose(...args) {
const length = args.length;
function dispatch(index, val) {
if (index === length) return val;
else {
args = args || [];
return args[index](dispatch(index + 1, val));
}
}
return (init) => dispatch(0, init);
}
const compose = (...fns) => ((params) => fns.reduce((prev, cur) => (prev = cur(prev ?? params), prev), null))
看了大佬的实现,感觉我的实现突然不香了