4

我试图了解 OCaml 中的物理相等运算符 (Pervasives.(==)Pervasives.(!=)) 的含义。

语言手册说表达式""是“常量”,而不是“表达式”:

6.5 常数

常量::== ...字符串文字

但我找不到任何表示常量是单独/预评估或池化的措辞,并且 REPL 表示可变字符串值(谢天谢地)没有被池化。

(* a *)  ""          == "";;             (* false *)
(* b *)  "foo"       == "foo";;          (* false *)
(* c *)  ""          == String.copy "";; (* false *)
(* d *)  ()          == ();;             (* true  *)
(* e *)  (42, -42)   == (42, -42);;      (* false *)
(* f *)  ("", 1)     == ("", 1);;        (* false *)
(* g *)  None        == None;;           (* true  *)
(* h *)  (Some None) == (Some None);;    (* false *)

19.3 OCaml 数据类型的表示”部分建议语言规范要求 bools、ints、chars、单位值、简单变体和空列表是无私的。

实现是否必须像上面那样才能成为符合 OCaml 的实现?

兼容的 OCaml 实现是否可以重写指针b以指向a何时a = b (* structurally *)为真,并且两者都是不可变类型的值(或有效的不可变值,如零长度字符串/数组),有时这样做是为了减少一代中可到达的较年轻值的数量GC?

4

2 回答 2

5

当我阅读语言规范时,很少有关于值何时不同的保证。我相信唯一的保证是在Pervasives 模块的文档中:

对于可变类型,例如引用、数组、字符串、具有可变字段的记录和具有可变实例变量的对象,当且仅当 e1 的物理修改也影响 e2 时,e1 == e2 为真。在非可变类型上, ( == ) 的行为取决于实现;但是,可以保证 e1 == e2 意味着比较 e1 e2 = 0。

关于 FP 的一个很酷的事情是编译器和运行时可以自由地用不可变的值做任意聪明的事情。所以这个保证是你真正想要的(恕我直言)。

总而言之,是的,运行时或编译器是免费的(同样,恕我直言)以任何它认为有帮助的方式共享(而不是共享)不可变值。

我不会将表示部分解释为语言规范的一部分。它只是当前实现的有用文档。

于 2012-08-05T22:39:48.347 回答
3

只是一个评论:字符串常量的池化方式与您测试的方式不同:

let f () = "foo"
let b = f () == f () (* true *)

如果您改变调用的输出,这确实可能会导致错误f ():这也会影响所有进一步的调用。关于这种行为的共识是可变字符串是一个历史错误(一个应该有一个不同于主要字符串类型的可变缓冲区类型,编码选择和连接复杂性应该更重要)并且语义破坏池足够有趣性能方面允许假设字符串常量没有发生突变。如果想避免池化,应该String.copy直接在字符串常量上调用 a 。

于 2012-08-13T08:34:36.670 回答