何时在OCaml中创建物理上不同的值?

何时在OCaml中创建物理上不同的值?,ocaml,object-identity,referenceequals,Ocaml,Object Identity,Referenceequals,我试图理解物理相等运算符(pervisives(==)和pervisives(!=))在OCaml中的含义 《语言手册》中说,表达式“是一个“常量”,而不是一个“表达式”: 常数::==。。。字符串文字 但我找不到任何措辞表明常数是单独/预先计算或合并的,REPL表明可变字符串值(谢天谢地)不是合并的 (* a *) "" == "";; (* false *) (* b *) "foo" == "foo";; (* f

我试图理解物理相等运算符(
pervisives(==)
pervisives(!=)
)在OCaml中的含义

《语言手册》中说,表达式
是一个“常量”,而不是一个“表达式”:

常数::==。。。字符串文字

但我找不到任何措辞表明常数是单独/预先计算或合并的,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 *)
第“”节建议语言规范要求bools、int、chars、单位值、简单变量和空列表是无私的

实现是否必须如上所述才能成为符合要求的OCaml实现


a=b(*structural*)
为true且两者都是不可变类型的值(或实际上不可变的值,如零长度字符串/数组)时,符合要求的OCaml实现能否将
b
处的指针重写为指向
a
正如有时为了减少一代GC中可到达的较年轻值的数量所做的那样?

当我阅读语言规范时,很少有关于值何时不同的保证。我认为唯一的保证是以下文件:

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

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

总之,是的,运行时或编译器可以自由(同样,IMHO)共享(而不是共享)它认为有用的不可变值


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

只是一句话:字符串常量的汇集方式与您测试的方式不同:

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

如果您改变
f()
调用的输出,这确实可能导致bug:这也会影响所有后续调用。关于该行为的共识是可变字符串是一个历史错误(应该有一个不同于主字符串类型的可变缓冲区类型,编码选择和连接复杂性应该更重要)而且,语义破坏池非常有趣,从性能角度考虑,它允许假设字符串常量没有变化。如果要避免共用,只需调用
字符串。直接在字符串常量上复制

谢谢。这很好地回答了两个问题:不存在像零长度数组这样的有效不可变值,并且允许对不可变值进行优化。它没有回答对于
a
b
a!=时间T0时的b
意味着a!=b
在时间T1>T0,如GC优化示例中所示。实际上,我认为别名措辞“当且仅当物理修改”确实允许
String.copy”“==”
,因为不可能观察到
实例的物理修改。