4

I'm trying to understand what the physical equality operators (Pervasives.(==) and Pervasives.(!=)) mean in OCaml.

The language manual says that the expression "" is a "constant", not an "expression":

6.5 Constants

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.

(* 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.

Does an implementation have to behave as above to be a complying OCaml implementation?

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?

4

2 に答える 2

5

言語仕様を読んでいると、値がいつ異なるかについての保証はほとんどありません。唯一の保証は、Pervasivesモジュールのドキュメントにあると思います。

参照、配列、文​​字列、可変フィールドを持つレコード、可変インスタンス変数を持つオブジェクトなどの可変タイプでは、e1の物理的変更がe2にも影響する場合に限り、e1==e2が真になります。変更不可能な型では、(==)の動作は実装に依存します。ただし、e1==e2はe1e2=0の比較を意味することが保証されています。

FPの優れた点の1つは、コンパイラーとランタイムが不変の値を使用して任意に巧妙なことを自由に実行できることです。したがって、この保証は、あなたが本当に欲しがるすべてのものです(IMHO)。

要するに、はい、ランタイムまたはコンパイラーは、不変の値を、役立つと思われる方法で自由に共有できます(共有しません)。

表現セクションを言語仕様の一部として解釈することはしません。これは、現在の実装に関する有用なドキュメントです。

于 2012-08-05T22:39:48.347 に答える
3

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. 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.

于 2012-08-13T08:34:36.670 に答える