简体   繁体   English

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

[英]When are physically distinct values created in OCaml?

I'm trying to understand what the physical equality operators ( Pervasives.(==) and Pervasives.(!=) ) mean in OCaml. 我试图理解物理相等运算符( Pervasives.(==)Pervasives.(!=) )在OCaml中的含义。

The language manual says that the expression "" is a "constant", not an "expression": 语言手册说表达式""是“常量”,而不是“表达式”:

6.5 Constants 6.5常数

constant ::== ... string-literal constant :: == ... string-literal

but I can't find any verbiage indicating that constants are singly/pre-evaluated or pooled, and the REPL indicates that mutable string values are (thankfully) not pooled. 但是我找不到任何表明常量是单独/预先评估或合并的,并且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 *)

Section " 19.3 Representation of OCaml data types " suggests that the language specification requires that bools, ints, chars, the unit value, simple variants, and empty lists are selfless. 19.3 OCaml数据类型的表示 ”一节表明,语言规范要求bool,int,chars,单位值,简单变体和空列表都是无私的。

Does an implementation have to behave as above to be a complying OCaml implementation? 实现是否必须像上面那样成为一个符合要求的OCaml实现?

Can a complying OCaml implementation rewrite the pointer at b to point to a when a = b (* structurally *) is true and both are values of an immutable type (or effectively immutable values like zero length strings/arrays) as is sometimes done to reduce the number of reachable younger values in a generational GC? 一个符合条件的OCaml实现可以重写b处的指针指向aa = b (* structurally *)为真且两者都是不可变类型的值(或有效不可变值,如零长度字符串/数组),有时会这样做减少代际GC中可达到的较年轻值的数量?

As I read the language spec, there are very few guarantees about when values are distinct. 当我阅读语言规范时,很少有关于何时值不同的保证。 I believe the only guarantee is in the documentation of the Pervasives module : 我相信唯一的保证是在Pervasives模块的文档中:

On mutable types such as references, arrays, strings, records with mutable fields and objects with mutable instance variables, e1 == e2 is true if and only if physical modification of e1 also affects e2. 在可变类型(如引用,数组,字符串,具有可变字段的记录和具有可变实例变量的对象)上,当且仅当e1的物理修改也影响e2时,e1 == e2才为真。 On non-mutable types, the behavior of ( == ) is implementation-dependent; 在非可变类型上,(==)的行为是依赖于实现的; however, it is guaranteed that e1 == e2 implies compare e1 e2 = 0. 但是,保证e1 == e2意味着比较e1 e2 = 0。

One of the cool things about FP is that the compiler and runtime are free to do arbitrarily clever things with immutable values. 关于FP的一个很酷的事情是编译器和运行时可以使用不可变值自由地做任意聪明的事情。 So this guarantee is about all you would really want to have (IMHO). 所以这个保证就是你真正想拥有的(恕我直言)。

In sum, yes, the runtime or the compiler is free (again, IMHO) to share (and not share) immutable values any way it thinks will be helpful. 总之,是的,运行时或编译器是免费的(再次,恕我直言)以任何它认为有用的方式共享(而不是共享)不可变值。

I wouldn't interpret the representation section as part of the language specification. 我不会将表示部分解释为语言规范的一部分。 It's just useful documentation of the current implementation. 它只是当前实现的有用文档。

Just a remark: String constants are pooled in a different way than what you test: 只是一个注释:字符串常量的汇集方式与您测试的方式不同:

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

This may indeed lead to bugs if you mutate the output of a f () call: this will affect all further calls as well. 如果你改变f ()调用的输出,这可能确实会导致错误:这也将影响所有进一步的调用。 The consensus on that behavior is that mutable string are an historical mistake (one should have a mutable buffer type distinct from the main string type, on which encoding choices and concatenation complexity should be more important) and that the semantics-breaking pooling is interesting enough performance-wise to be allowed to assume that string constants are not mutated. 关于该行为的共识是可变字符串是一个历史错误(一个应该具有与主字符串类型不同的可变缓冲区类型,编码选择和连接复杂性应该更重要)并且语义破坏池很有趣性能方面允许假设字符串常量没有变异。 If one want to avoid pooling, one should just call a String.copy directly on the string constant. 如果想要避免池化,则应该直接在字符串常量上调用String.copy

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM