对于关联运算f
在数组的元素上a
,以下关系应该成立:a.reduce(f)
应该等于a.reduceRight(f)
.
事实上,它确实适用于结合运算和交换运算。为了
例子:
const a = [0,1,2,3,4,5,6,7,8,9];
const add = (a, b) => a + b;
console.log(a.reduce(add));
console.log(a.reduceRight(add));
然而,它不适用于结合但不可交换的运算。例如:
const a = [[0,1],[2,3],[4,5],[6,7],[8,9]];
const concat = (a, b) => a.concat(b);
console.log(JSON.stringify(a.reduce(concat)));
console.log(JSON.stringify(a.reduceRight(concat)));
我们需要翻转以下论点f
for reduceRight
使它们等效:
const a = [[0,1],[2,3],[4,5],[6,7],[8,9]];
const concat = (a, b) => a.concat(b);
const concatRight = (b, a) => a.concat(b);
console.log(JSON.stringify(a.reduce(concat)));
console.log(JSON.stringify(a.reduceRight(concatRight)));
这让我相信本机实现reduceRight
是错的。
我相信reduceRight
函数应实现如下:
var REDUCE_ERROR = "Reduce of empty array with no initial value";
Array.prototype.reduceRight = function (f, acc) {
let { length } = this;
const noAcc = arguments.length < 2;
if (noAcc && length === 0) throw new TypeError(REDUCE_ERROR);
let result = noAcc ? this[--length] : acc;
while (length > 0) result = f(this[--length], result, length, this);
return result;
};
Since result
表示前一个值(右侧值),将其作为函数的第二个参数是有意义的f
。当前值代表左侧值。因此,将当前值作为函数的第一个参数是有意义的f
。这样,即使对于非交换结合运算,上述关系也成立。
所以,我的问题是:
- 这难道不是更有意义吗
reduceRight
按照我的方式实施?
- 为什么是本土人
reduceRight
没有按照我的方式实施?
这难道不是更有意义吗reduceRight
按照我的方式实施?
或许。然而,JavaScript数组迭代器不是来自纯函数式编程背景。
为什么是本土人reduceRight
没有按照我的方式实施?
因为具有相同的参数顺序更简单(更容易记住),所以累加器总是第一个。
数组的原始操作是reduce
,一如既往地从 0 迭代到 n-1。仅在具有递归构建列表的 Haskell 中foldr
更有意义(有build
对偶性,在无限列表上惰性地工作得很好......)。注意命名方式不是这样的reduce
+reduceLeft
…
Then reduceRight
不反转折叠操作,它只是reverses the 迭代命令。这也是文档和教程中通常解释的方式,例如权威指南:
reduceRight()
就像reduce()
,除了它从最高处处理数组。
还有第一次实施 https://bug363040.bugzilla.mozilla.org/attachment.cgi?id=248586 of reduce
/reduceRight
(see 错误 363040 https://bugzilla.mozilla.org/show_bug.cgi?id=363040) in 莫斯拉的数组附加项 http://lxr.mozilla.org/mozilla/source/js/src/jsarray.c#2878JS 1.8 遵循这种方法:它只是翻转开始和结束并否定步骤值。
The 戴夫·赫尔曼的笔记 https://mail.mozilla.org/pipermail/es-discuss/2009-March/009067.htmlES4 规范遵循了这个思路。它确实提到了Haskell,但是整个文档没有处理Haskell的参数顺序callback
根本不。也许 Haskells 不常见的语法或规范类型名称中丢失了不同的顺序,因此两个签名都以(a -> b -> …
。更多的讨论进入missing thisObject范围 https://stackoverflow.com/q/14867946/1048572.
一些相关摘录:
[该方法]的好处:
- 就像 Python => Python 社区心态一样
- 折叠的完整通用性(左)
- 但也要做出简单的情况,其中第一个元素是基础
元素,更简单
我猜大多数人都会找到从左到右的减少更多版本
直观,因为它们通常从左到右迭代数组。
另外,这就是 Python 所做的。
我认为提供一个reduceRight也很重要,
因为并非每个操作都是关联的,有时人们需要
从右向左走。
最后,就是这样:
阵列附加功能:按 FF 当前支持的方式指定
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)