首页 > 解决方案 > OCaml 和 ReasonML 的结果不同

问题描述

有一种情况将两个向量映射为一个向量。我预计两个 ML 的结果应该是相同的。不幸的是,ReasonML 的结果是不同的。请帮助并评论如何解决它。

OCaml

List.map2 (fun x y -> x+y) [1;2;3] [10;20;30];;
[11;;22;;33]

原因机器学习

Js.log(List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30]))
[11,[22,[33,0]]]

标签: listocamlreasonbucklescript

解决方案


结果相同的,但是您使用了不同的打印方法。如果Js.log您不使用rtopor sketch.sh,您将获得您期望的输出:

- : list(int) = [11, 22, 33]

Js.log打印它的方式不同,因为它是一个 BuckleScript 绑定到console.log,它将打印你给它的值的JavaScript 表示。JavaScript 中不存在列表,只有数组存在。

BuckleScript 表示列表的方式与它在本地完成的方式几乎相同。OCaml 和 Reason 中的列表是一个“cons-cell”,它本质上是一个元组或 2 元素数组,其中第一项是该单元格的值,最后一项是指向下一个单元格的指针。list类型本质上是这样定义的:

type list('a) =
  | Node('a, list('a))
  | Empty;

有了这个定义,可以用以下方式构建:

Node(11, Node(22, Node(33, Empty)))

它在 JavaScript 中表示如下:

[11,[22,[33,0]]]
 ^   ^   ^  ^
 |   |   |  The Empty list
 |   |   Third value
 |   Second value
 First value

列表是这样定义的,因为不变性使得这种表示非常有效。因为我们可以添加或删除值,而无需将旧列表中的所有项目复制到新列表中。要添加一个项目,我们只需要创建一个新的“cons-cell”。使用具有想象中的不变性的 JavaScript 表示:

const old = [11,[22,[33,0]]];
const new = [99, old];

并且要从前面移除一个项目,我们不需要创建任何东西。我们可以只获得对子列表的引用并重新使用它,因为我们知道它不会改变。

const old = [11,[22,[33,0]]];
const new = old[1];

列表的缺点是在末尾添加和删除项目相对昂贵。但在实践中,如果您以函数式的方式构建代码,使用递归,列表将非常自然地使用。而且效率很高。


推荐阅读