JavaScript中reduceRight的原生实现是错误的

2024-01-06

对于关联运算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。这样,即使对于非交换结合运算,上述关系也成立。

所以,我的问题是:

  1. 这难道不是更有意义吗reduceRight按照我的方式实施?
  2. 为什么是本土人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(使用前将#替换为@)

JavaScript中reduceRight的原生实现是错误的 的相关文章

随机推荐

  • docker容器内的Python,优雅地停止

    我正在运行一个非常基本的 Python 循环示例Windows docker 容器 我愿意优雅地停下来 该脚本在我的 dockerfile 中以这种方式启动 CMD python exe test py 在 docker 文档中说SIGTE
  • Mysql连接两个表

    我需要连接两个表 请帮助我
  • Plotly:如何向现有绘图添加箭袋?

    我想用plotly python 将箭袋添加 到现有图形中 但我能找到的唯一平静的文档要么只创建一个箭袋 here https plotly github io plotly py docs generated plotly figure
  • 在 C# 中将十六进制字符串转换为其数值[重复]

    这个问题在这里已经有答案了 我的表格上有一个文本框 我想将 0x31 作为字符串写入文本框 然后当我单击按钮时 我想将此字符串转换为 0x31 作为十六进制值 我如何将此字符串转换为十六进制值 int i Convert ToInt32 0
  • 指针算术:越界而不取消引用

    我想知道以下代码是否不被 C 标准接受 int n 10 double p new double 0 double q p n std cout lt lt n lt lt static cast
  • Motorola MC3190 手持计算机 Windows 6.0 ce 上的任务管理器

    我试图找出为什么网页会导致 Motorola MC3190 内存泄漏 条形码扫描仪是 Windows 6 0 CE 中的新增功能 没有安装任何程序 仅默认安装 我们只使用IE 当我们使用它两周后 扫描仪内存耗尽并且崩溃了 完全重新启动后 一
  • Android 模拟器对 Xamarin 的 AMD 进程没有响应问题

    当我将 Windows 更新到 Windows 11 时 我注意到当我为 Xamarin 项目运行 Android 模拟器时 它冻结并表示没有响应 我尝试了以下这些项目 但无法解决我的问题 减小仿真器设备的 RAM 大小 降低模拟器设备的分
  • 电子邮件字符串集合的 JPA 验证

    我的 bean 中有一个字符串列表 这些字符串是电子邮件 我想验证它们 Email ElementCollection fetch FetchType LAZY OrderColumn private List
  • 更快地实现对所有可能组合的过滤

    考虑我有一个像这样的数据框 set seed 1 q lt 100 df lt data frame Var1 round runif q 1 50 Var2 round runif q 1 50 Var3 round runif q 1
  • 画布上的drawImage在firefox中具有奇怪的宽高比和其他问题

    我运行的是 Firefox 3 5 6 我想在画布上显示图像并在其上绘制几条线 它需要在 Firefox 和 Internet Explorer 使用 excanvas 中正确显示 这是我得到的 上图是我在 IE8 中看到的 下图是我在 F
  • 字典理解中的 if-else [重复]

    这个问题在这里已经有答案了 是否可以使用else声明 如果是 如何 dictcomp 无法使用else作为理解本身的一部分 参见this https docs python org 3 reference expressions html
  • 如何在Linux中查询Vsync相位

    我需要创建一个 C 函数 它将返回下一个 Vsync 间隔之前的秒数作为浮点值 Why 我正在创建显示跟随鼠标光标的矩形的程序 表面上OpenGL在glXSwapBuffers函数中提供了垂直同步机制 但我发现这是不可靠的 使用某些卡驱动程
  • Masonry 不适用于动态内容

    Masonry 无法处理我的动态内容 我不知道为什么 我不认为这是我这边的错误 至少我已经查看了代码几个小时了 我找不到任何不起作用的东西 reads listbox php and cycles through the array cal
  • 在 GCP 上部署 Weaviate k8s 设置时,无法在 API 组中列出资源“configmaps”

    运行时 在 GCP 上 helm upgrade values values yaml install namespace weaviate weaviate weaviate tgz 它返回 UPGRADE FAILED Error co
  • 键入时向数字添加逗号

    我试图在用户输入数字时添加逗号 选择的正确语法是什么input form control带属性的类number输入Jquery 编辑 我无法更改 HTML 代码 因为它是使用 Bootstrap 从 Django 输出的 HTML span
  • 为什么宇宙飞船运算符里面只有一个等号?

    为何宇宙飞船操作员 lt gt 选择有一个等号而不是两个 这是否被视为与一个等号 通常表示赋值 和两个等号 通常表示比较 不一致 为什么会有两个 里面只有一个 lt gt and 这一点也不矛盾 仅有的 不一致 这是为了避免与赋值运算符发生
  • 如何编写惯用的构造函数

    我对 Go 中的构造函数感到困惑 我见过的大多数构造函数都会返回一个结构体 但 Effective Go 表明在某些情况下可以返回一个接口 根据 普遍性 规则 https golang org doc effective go html g
  • 标志“-D_POSIX_C_SOURCE=200112L”是什么意思?

    没有它 我无法使用连接到互联网所需的库 但我不知道这意味着什么 D POSIX C SOURCE 200112L 谁能解释一下吗 随着时间的推移 POSIX 经历了多次修订 每个新版本都更改了它支持的功能集 该宏定义了您希望使用哪组功能来构
  • 哪里需要(不需要)完整的类型?

    我最近惊讶地发现这段代码可以编译 至少在 gcc 和 MSVC 上 template
  • JavaScript中reduceRight的原生实现是错误的

    对于关联运算f在数组的元素上a 以下关系应该成立 a reduce f 应该等于a reduceRight f 事实上 它确实适用于结合运算和交换运算 为了 例子 const a 0 1 2 3 4 5 6 7 8 9 const add