返回函数时,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
,然后计算 f
。 f(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'));
下面的代码是函数式写的。有一个要进行购买的用户对象。流程如下:商品加入购物车,加税,商品被购买,推入用户的购买记录数组。最后,原来的购物车被清空了。这一切都是通过使用 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
,然后计算 f
。 f(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'));