javascript - compose 函数如何处理多个参数?
问题描述
这是我需要改进的“撰写”功能:
const compose = (fns) => (...args) => fns.reduceRight((args, fn) => [fn(...args)], args)[0];
这是一个实际的实现:
const compose = (fns) => (...args) => fns.reduceRight((args, fn) => [fn(...args)], args)[0];
const fn = compose([
(x) => x - 8,
(x) => x ** 2,
(x, y) => (y > 0 ? x + 3 : x - 3),
]);
console.log(fn("3", 1)); // 1081
console.log(fn("3", -1)); // -8
这是我的导师提出的改进。
const compose = (fns) => (arg, ...restArgs) => fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);
如果我们在第一次迭代中传递像 func(x, [y]) 这样的参数列表,我仍然不明白我们如何使函数与 [y] 的解压缩数组一起工作?
解决方案
让我们分析一下改进后的compose
作用
compose = (fns) =>
(arg, ...restArgs) =>
fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);
当您compose
输入许多功能时,您会返回……一个功能。在你的情况下,你给它一个名字,fn
.
这个fn
功能是什么样的?通过简单的替换,您可以将其视为:
(arg, ...restArgs) => fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);
哪里fns === [(x) => x - 8, (x) => x ** 2, (x, y) => (y > 0 ? x + 3 : x - 3)]
。
因此,您可以为这个函数fn
提供一些参数,这些参数将与 ; 进行“模式匹配” (arg, ...restArgs)
。在您的示例中,当您调用fn("3", 1)
, arg
is"3"
和restArgs
is时[1]
(因此...restArgs
扩展到1
逗号之后,因此您会看到fn("3", 1)
减少为
fns.reduceRight((acc, func) => func(acc, 1), "3");
从这里你可以看到
- 最右边的函数,
(x, y) => (y > 0 ? x + 3 : x - 3)
用两个参数"3"
(的初始值acc
)和调用1
, - 结果将通过以下调用作为第一个参数传递给中间函数
func
, - 等等,
但关键是 的第二个参数func
,即1
,只被最右边的函数使用,而它被传递给其他两个函数但被忽略了!
结论
函数组合是一元函数之间的事情。将它与具有高于 1 的元数的函数一起使用会导致混淆。
例如考虑这两个函数
square = (x) => x**2; // unary
plus = (x,y) => x + y; // binary
你能谱写它们吗?好吧,您可以将它们组合成这样的函数
sum_and_square = (x,y) => square(plus(x,y));
compose
您在问题底部获得的功能会很顺利:
sum_and_square = compose([square, plus]);
但是,如果您的两个功能是这些呢?
apply_twice = (f) => ((x) => f(f(x))); // still unary, technically
plus = (x,y) => x + y; // still binary
你的compose
行不通。
即使,如果函数plus
被柯里化,例如,如果它被定义为
plus = (x) => (y) => x + y
然后可以考虑将它们组合成一个函数,如下所示:
f = (x,y) => apply_twice(plus(x))(y)
这可以预见地产生f(3,4) === 10
.
你可以得到它作为f = compose([apply_twice, plus])
.
美容改善
此外,我建议进行“化妆品”更改: make compose
accept...fns
而不是fns
,
compose = (...fns)/* I've only added the three dots on this line */ =>
(arg, ...restArgs) =>
fns.reduceRight((acc, func) => func(acc, ...restArgs), arg);
并且您将能够在没有 groupint 的情况下调用它来将要组合在数组中的函数,例如,您将编写compose(apply_twice, plus)
而不是.compose([apply_twice, plus])
顺便说一句,有lodash
该库中有两个函数可以处理函数组合:
_.flow
_.flowRight
, 别名为_.compose
inlodash/fp
推荐阅读
- apache-spark - pyspark 从 AWS S3 读取文件不起作用
- python - 正则表达式无序重复匹配
- python - subprocess.run“无结束引号”的格式化字符串
- excel - 如何仅使用 vba 代码对二维数组中的一列数字进行排名
- ios - Mac10.14、10.14 vm 的 xcode 无法在 azure 托管代理上启动模拟器以进行 reactnative 构建
- azure-web-app-service - 如何通过 Azure 资源管理器设置 Azure 应用服务以在 .Net Core 上运行
- unity3d - Unity:为什么我不能控制玩家?
- c# - 统一的 ARCore 将让我运行游戏但不能构建和运行
- python - 将非时间数据上采样到整数米
- python - 新手在 if 语句之后的某种循环中