在我之前的问题中:
@Aadit M Shah 给了我惊人的解决方案,如下所示:
https://stackoverflow.com/a/51420884/6440264
给定一个像A(a)(b)(f)
where f
is a function 这样的表达式,不可能知道是否f
应该将其添加到列表中,或者它是否是归约函数。因此,我将描述如何编写表达式,例如A(a)(b)(f, x)
which 等价于[a, b].reduce(f, x)
. 这使我们能够根据您提供的参数数量来区分列表何时结束:
const L = g => function (x, a) {
switch (arguments.length) {
case 1: return L(k => g((f, a) => k(f, f(a, x))));
case 2: return g((f, a) => a)(x, a);
}
};
const A = L(x => x);
const xs = A(1)(2)(3)(4)(5);
console.log(xs((x, y) => x + y, 0)); // 15
console.log(xs((x, y) => x * y, 1)); // 120
console.log(xs((a, x) => a.concat(x), [])); // [1,2,3,4,5]
它由于延续而起作用。每次我们添加一个新元素,我们都会累积一个 CPS 函数。每个 CPS 函数调用前一个 CPS 函数,从而创建一个 CPS 函数链。当我们给这个 CPS 函数链一个基函数时,它会展开链并允许我们减少它。换能器和镜头背后的想法相同。
我还有2个问题。
为了区分 reduce 函数,我考虑了一些使用反射的自定义 Typing 机制,但是为了专注于这个问题,到目前为止我想简单地应用
const isReducer = f => (typeof f === 'function');
提供初始值的要求对折叠/归约有限制,例如,不可能为归约提供二进制操作的初始值,例如
常量头 = (a, b) => a; 常量尾 = (a, b) => b;
(除非您手动提供第一个/最后一个值,这对运行代码没有意义)理论上,每个二进制操作都有一个标识值,但是不可能按原样提供。唯一的方法是抽象为一个身份。
话虽如此,我无法将提供的代码重构为单个参数和函数的 reducer 类型,并将默认值作为序列的初始值。
你能提供重构的代码吗?此外,此示例的传感器/CPS 的任何信息都值得赞赏。