我看到 reduce 被传递了一个匿名函数而不是 combine 函数
这不是真的。匿名函数就是combine
函数。
combine(base, element)
对比function(total, element)
这两个函数调用本质上是相等的:combine(base,element) 和 function(total,element)?
不,它们是完全不同的东西。
前者是函数调用,对 . 引用的函数进行调用combine
。
然而,第二个计算为一个新的函数值。如果是:
reduce(function(total, element) {...}, ...);
reduce()
正在传递一个函数值,这意味着创建了一个新函数,该函数接受两个参数(用and表示)。然后将此函数传递给.total
element
reduce
让我从昨天开始回收我的可视化。重要的是要意识到,这不仅适用于您的案例,而且适用于reduce(left)概念的每个实施例。
return value of reduce()
/
etc ...
/
combine
/ \
combine xs[2]
/ \
combine xs[1]
/ \
0 xs[0]
当然,这仅显示发生了什么,而不是如何,我认为在您的情况下您要询问how。只要记住这个可视化,看看结果会发生什么。
替换函数
为了更清楚地说明发生了什么,我将逐步替换正在传递的函数。
程序开始:
function countZeroes(array) {
return count(equals(0), array);
}
equals(0)
(你可以称之为柯里化的一种形式)计算一个函数,该函数被传递给count()
.
这基本上导致以下count()
功能:
function count(array) {
return reduce(function(total, element) { // Where is the value for total coming from?
return total + (0 == element ? 1 : 0);
}, 0, array);
}
从这里,我们可以提取combine
参数:
function combine(total, element) { // Where is the value for total coming from?
return total + (0 == element ? 1 : 0);
}
那就是在reduce函数中使用的函数:
function reduce(base = 0, array) {
forEach(array, function (element) {
base = combine(base, element);
});
return base;
}
reduce(0, array)
从count()
函数中调用。forEach
考虑到我们的帐户实现,现在可以像这样重写传递给的函数combine
:
function reduce(base = 0, array) {
forEach(array, function (element) {
base = base + (0 == element ? 1 : 0);
});
return base;
}
请记住,这base
代表我们的total
.
作为我们的最后一步,我们会考虑做什么forEach()
。
function reduce(base = 0, array) {
for (var i = 0; i < array.length; i++)
base = base + (0 == array[i] ? 1 : 0);
}
return base;
}
所以这就是count()
本质上的样子,所有调用都未包装:
function count(array) {
var base = 0;
for (var i = 0; i < array.length; i++)
base = base + (0 == array[i] ? 1 : 0);
}
return base;
}