返回函数时,reduce 函数如何工作?还想了解更多关于 compose 和 composition

How does the reduce function work when a function is returned? Would also like to know more about compose and composition

下面的代码是函数式写的。有一个要进行购买的用户对象。流程如下:商品加入购物车,加税,商品被购买,推入用户的购买记录数组。最后,原来的购物车被清空了。这一切都是通过使用 reduce 函数完成的,该函数传递了一个 compose 函数。

我很难理解的是 reduce 函数在这种情况下是如何工作的。根据我的理解,compose 函数作为 reduce 的回调函数传入。在 compose 函数中,f 代表累加器,g 代表数组中的一项。

 const user = {
  name: 'Kim',
  active: true,
  cart: [],
  purchases: []
}

const compose = (f,g) => (...args) =>  {
  console.log(1, f);
  console.log(2, g);
  return f(g(...args));
  }

// The below code is commented out so that I can visualize it in a more simple manner
//purchaseItem (
 // emptyCart,
 // buyItems,
  //applyTaxToItems,
 // addItemToCart
//)(user, {name: 'laptop', price: 244});

function purchaseItem(...fns) {
  console.log(fns);
  return fns.reduce(compose);
}

// Here is each piece broken down to be passed into reduce and the arguments the compose function takes
console.log([emptyCart , buyItems, applyTaxToItems, addItemToCart].reduce(compose)(user, {name: 'laptop', price: 244}));

function addItemToCart(user, item) {
  const updateCart = user.cart.concat(item);
  return Object.assign({}, user, { cart: updateCart });
}

function applyTaxToItems(user, item) {
  return user
}

function buyItems(user, item) {
  return user
}

function emptyCart(user, item) {
  return user
} 

输出结果如下:

1 [Function]
2 [Function: addItemToCart]
1 [Function]
2 [Function: applyTaxToItems]
1 [Function: emptyCart]
2 [Function: buyItems]
{ name: 'Kim',
  active: true,
  cart: [ { name: 'laptop', price: 244 } ],
  purchases: [] }  

我试图映射 f 和 g 元素的流程。我知道 f 将保留 compose 函数 returns 的任何值,但为什么初始值是匿名函数。此外,为什么 item 元素从数组中的最后一个元素开始并向后工作?我也很困惑为什么 emptyCart 函数在 reduce 的最后一个循环中成为 f 值。如果有人能向我解释这一点,我将不胜感激。谢谢。

您的日志没有正确映射执行流程。

您首先记录 f,然后记录 g,但是对于 f(g(x)),首先计算 g,然后计算 ff(g(x) 可以读作“f after g of x”或“f of g of x”。

以同样的方式,当您使用像 f(g(...x)) 这样的缩减器来缩减函数数组时,它们将以相反的顺序进行计算,因为您得到的函数的行为类似于 f(g(h(x)))

查看下面的代码以获得更多解释。 compose2 与您的 compose 函数相同,但具有更繁重的日志记录。

如果您 运行 下面的代码,您可能会更好地了解发生了什么。为了评估 reduction/composition 创建的函数,我们评估 f(g(...args)).

形式的多个函数

注意 g(...args) 的结果如何在最终结果向下传播之前全部向上传播。

const compose2 = (f, g, i) => {
  const name = `${f.name} after ${g.name}`;
  const h = {[name]: (...args) =>  {
    console.log(i, 'f:', f.name);
    console.log(i, 'g:', g.name);
    console.log(i, 'args to g:', ...args);
    console.log(i, 'g(...args):', g(...args));
    console.log(' ');
    const res = f(g(...args));
    console.log(i, 'result:', res);
    return res;
  }}[name];
  return h;
}

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(compose2)('a','b'));