Javascript 功能性 composition/sequencing

Javascript functional composition/sequencing

我正在尝试通过练习来理解 Javascript 中的构图和“排序”概念:

Def. "composition" compose(f,g)(x) = f(g(x))

Def. "sequencing" sequence(f,g)(x) = g(f(x)) for more args sequence(f,g)(...args) = g(f(...args))

const sequence2 = (f1, f2) => (...args) => f2( f1(...args) );
const sequence = (f1, ...fRest) => fRest.reduce(sequence2, f1);

const f1 = (a, b) => {
    console.log(`[f1] working on: ${a} and ${b}`);
    return a + b;
}

const f2 = a => `Result is ${a}`;

const sequenceResult = sequence(f1, f1, f2)(1, 2, 5);
console.log(sequenceResult);

控制台显示:

[f1] working on: 1 and 2
[f1] working on: 3 and undefined
Result is NaN

似乎序列中的第二个函数无法访问 args:我缺少某些东西或者处理参数的方法不正确? (序列函数适用于没有参数的函数)。

这里是JSFiddle

It seems that the second function in the sequence can't access the args

是的,这是正常的,也是意料之中的。根据你给出的定义,

sequence(f1, f1, f2)(1, 2, 5);

等同于

f2(f1(f1(1, 2, 5)));

当然,f2 和外部 f1 都不能访问传递给内部 f1 的参数。

仅对 return 单个值起作用。有两种方法可以通过多个 return 值扩充函数:

  • return 像元组这样的数组
  • 而不是 return调用延续

这是后者的一个有趣实现,它明确不适用于任何生产代码:

const pipek = g => f => x => y => k =>
  k(g(x) (y) (f));

const addk = x => y => k =>
  (console.log("apply addk to", x, y), k(x + y));

const main = pipek(addk)
  (addk)
    (2)
      (3)
        (k => k(4)); // we have to pass the 4th argument within the continuation

console.log(main(x => x)); // escape from the continuation

请注意,所有函数都是柯里化的,我使用了术语 pipe,这是 JS 中反向函数组合的常用术语。