javascript - 将这个 compose 函数传递给 Javascripts reduce 的执行流程是什么?
问题描述
我只想知道在以下代码的情况下reduce是如何工作的(这是由stackoverflow用户在我之前的问题中提供的,我问这个问题是因为他的代码片段导致我有更多的问题没有被清除并且太长,不适合评论部分)。一个函数数组被传递到一个reducer。有一个 compose 函数在函数数组上运行。根据我的理解,这个 f 是累加器,而 g 是数组中的下一项。reduce 的每个周期返回的内容成为下一个周期的累加器。如果没有传入 reduce 的 initalValue 参数,则数组中的第一项将用作初始累加器值。
const compose = (f, g, i) => (...args) => {
console.log(i, g);
console.log(i, f);
return f(g(...args));
}
const f_xe = (x) => x + 'e',
f_xd = (x) => x + 'd',
f_xc = (x) => x + 'c',
f_xy = (x, y) => x + y;
console.log([f_xe, f_xd, f_xc, f_xy].reduce(compose)('a','b'));
// 3 [Function: f_xy]
// 3 [Function]
// 2 [Function: f_xc]
// 2 [Function]
// 1 [Function: f_xd]
// 1 [Function: f_xe]
// abcde
我把它想象成这样:
cycle #1:
f = f_xe
g = f_xd
return f(g(...args))
^ which is f_xe(f_xd('a', 'b'))
cycle #2:
f = what was returned previously
^^ which will be f_xe(f_xd('a', 'b'))
g = f_xc
return f(g(...args))
^^ which is f_xe(f_xd('a', 'b'))(f_xc('a', 'b'))
我已经知道这种思路是错误的,因为流程以封装的方式工作,就像这样:f_xe(f_xd((f_xc(f_xy('a', 'b')))))
但为什么会这样。如果有人可以错综复杂地解释为什么它以这种方式包装并逐步分解reduce的每个循环,那将不胜感激。我想知道的另一件事是,为什么不尝试在第一个周期立即评估?f_xe(f_xd('a', 'b'))
当返回这段代码时,它不会尝试评估它并产生错误,而不是继续处理数组中的下一项吗?相反,代码从数组中的最后一项开始计算,即使 compose 函数被指示从头开始应用。我确实理解,对于组合函数,最后一项将首先运行,然后以此类推,但是控制台日志语句不应该按从前到后的顺序运行吗?
再一次,我知道我的思路与这个完全不同,但我希望如果我分享我的思路,有人可以把它推向正确的方向。感谢任何可以对此有所了解的人。
解决方案
首先忘记'a'
and'b'
参数。重要的部分是
const f = [f_xe, f_xd, f_xc, f_xy].reduce(compose);
这是我们需要关注的,也是我们可以应用 for 定义的地方reduce
。的呼唤f('a','b')
稍后来。
扩展reduce
调用时,我们发现
const f = compose(compose(compose(f_xe, f_xd, 1), f_xc, 2), f_xy, 3);
(这实际上有点奇怪。我建议使用reduceRight
组合函数。还将识别函数作为累加器的初始值传递。)
现在我们可以扩展compose
调用:
const f1 = (...args) => {
console.log(1, f_xe);
console.log(1, f_xd);
return f_xe(f_xd(...args));
}
const f2 = (...args) => {
console.log(2, f1);
console.log(2, f_xc);
return f1(f_xc(...args));
}
const f3 = (...args) => {
console.log(3, f2);
console.log(3, f_xy);
return f2(f_xy(...args));
}
const f = f3;
现在,当您调用 时f3('a', 'b')
,您可以看到日志为什么会“向后”发生。
控制台日志语句不应该按从前到后的顺序运行吗?
如果你想要这样,你最好把它们放在compose
函数中,而不是放在它返回的闭包中。尝试
const compose = (f, g, i) => {
console.log(i, g);
console.log(i, f);
return (...args) => f(g(...args));
}
推荐阅读
- constraint-programming - How to use Picat to create CNF files from Minizinc files?
- python - 如何将现有对象放入共享内存?
- php - 如何在 PHP json_encode 中转义撇号
- postgresql - 在 PostgreSQL 中反透视数据
- java - Maven:读取程序集时出错:未找到程序集描述符
- javascript - 用(引导)模式的一个替换主滚动条
- sabre - 有没有办法从军刀队列中提取所有信息?
- openstreetmap - 如何查询比 x 长或短的桥?
- bash - 我可以在列有换行符的 bash 中使用“列”吗?
- c++ - 成员函数指针模板替换失败