OCaml中记录和元组有什么区别?

6

记录和元组之间是否存在除语法差异以外的差异?

是否存在性能差异?

元组和记录的实现是否相同?

您有哪些使用元组但无法使用记录(反之亦然)的示例?


什么引起了这种问题?它们适用于不同的应用。我在这个阶段不会担心性能问题。实现并不是“相同的”,因为它们是不同的东西。 - Asherah
如果它们是不同的东西,那么你有使用元组而不能使用记录(反之亦然)的示例吗?我问这个问题是因为你所说的两件事在我看来非常相似。 - Thomash
定义“可以完成”。请原谅这种傲慢的语气,但是使用图灵机器可以完成任何事情。记录只是提供更容易的访问方式,即您不需要拆解整个内容就可以访问一个元素。它们更好地记录了信息,并且与更容易的访问一起,使用mutable关键字和<-语法允许更容易地更新引用。 - Asherah
我的意思是,你会同意列表和元组是不同的,对吧?但是如果你很傻,它们可以被用作相同的方式。 - Asherah
4
@Len: 这是不同性质的问题。Thomash的问题完全合理。从类型论的角度来看,元组和记录只是产品类型(一个未标记,另一个标记,但这是一个相对较小的区别),具有常数宽度但异构组件。确实有点冗余,OCaml同时具有这两种类型(再加上对象类型作为第三种形式的乘积)。但是列表是递归的总和类型,长度未指定但组件是同构的,所以它是完全不同的东西。 - Andreas Rossberg
2个回答

21

在模块语法方面,它们几乎相同。主要的语义差异在于元组是结构类型,而记录是名义类型。这意味着记录可以是递归的,而元组不能(至少没有使用-rectypes选项时):

type t = {a : int, b : unit -> t}  (* fine *)
type u = int * (unit -> u)         (* error *)

此外,记录可以具有可变字段,而元组则不行。
值得一提的是,在OCaml的姊妹语言SML中,元组实际上就是记录。也就是说,在SML中,(a,b,c)只是语法糖,等同于{1=a,2=b,3=c},而记录也是结构类型。

1
关于可变字段,没有任何阻止你定义 type v = int * int ref 然后说 snd some_v := 90210 - Asherah
1
谢谢回答。你了解性能差异吗? - Thomash
1
@Len:是的,但实际上它是OCaml中嵌套在元组中的记录,其中 'a ref = {mutable content: 'a}。也就是说,您有额外的间接引用。最终,可变性始终与记录相关。 - Andreas Rossberg
1
@Thomash:就性能而言,两者应该没有任何区别。它们都编译成相同的东西。 - Andreas Rossberg
4
对于浮点数值,有一个例外。只包含浮点字段的记录将编译为比仅包含浮点元素的元组更高效的形式(浮点数未装箱)。 - hcarty
@hcarty:确实,我应该提到这一点。 - Andreas Rossberg

12

仅包含浮点数的记录或数组中的float字段将以未装箱的形式存储,而对元组没有这样的优化。如果您正在存储大量仅为浮点数的值,则使用记录非常重要 - 并且您可以通过将混合的浮点/其他数据结构拆分为内部仅包含浮点数的记录来获得优势。

另一个区别在于类型层面,并已由安德烈亚斯描述过 - 记录是生成的,而元组是预先存在并具有结构语义。如果您想要具有多态访问器的结构记录,可以使用对象类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接