2012-11-07 30 views
5

我一直在阅读ocaml文档,但我不能解释{ x with ... }如何适用于可变字段。该closest I've found可变记录字段和{x带...}

6.7表达式

expr := ... 
    ∣ { expr with field = expr { ; field = expr } [;] } 

...

记录

表达{ expr with field1 = expr1 ; … ; fieldn = exprn }建立与fields field1 … fieldn等于expr1 … exprn一个新记录,并且具有相同的所有其他领域值在记录expr。换句话说,它将返回记录expr浅副本,除了字段field1 … fieldn,它们被初始化为expr1 … exprn

“浅拷贝”的措辞可以解释为mutable字段没有提到共享存储空间或可以引用嵌套记录。当我测试(使用“OCaml的顶层,版本4.00.1”),从而

type t = { mutable x : int; mutable y: int } 
let a = {x=42;y=123} 
let b = { a with y=124} 
let _ = a.x <- 43 
let _ = Printf.printf "b.x=%d\n" b.x 
;; 

我得到的结果表明b.x不别名a.x

b.x=42 
type t = { mutable x : int; mutable y : int; } 
val a : t = {x = 43; y = 123} 
val b : t = {x = 42; y = 124} 

这让我很高兴,但我想确保

{ e with fi=x } 

的东西是有效的语法糖一样

(let tmp=e in { f0=tmp.f0; … fi-1=tmp.fi-1; fi=x; fi+1=tmp.fi+1; …; fn=tmp.fn }) 

mutable字段不能由ref支持,实现可以重用,而不是分配新的可变存储。

+1

所以,你只是希望我们确认 '{É具有f = X}' 是'有效语法糖(让{F0 = tmp.f0 TMP = E; ... FI-1 = TMP。 fi-1; fi = x; fi + 1 = tmp.fi + 1; ...; fn = tmp.fn})'... etc? –

+0

@RobertHarvey,其他文档的指针或如何阅读这些文档的解释会有所帮助,但任何知道什么是和不是未定义行为的人都会有所帮助。 –

回答

3

我所见过的每一处“浅拷贝”都意味着,即使在所有字段总是可变的语言中,像Java一样,只需通过赋值即可将所有组件转移过来。所以在这种情况下,(let tmp=e in { f0=tmp.f0; … fi-1=tmp.fi-1; fi=x; fi+1=tmp.fi+1; …; fn=tmp.fn })正是它的意思。

+0

如果'mutable'是用'ref'作为语法糖来实现的,so'{mutable i:int}'是'{i:int ref}'和'{i = 42}'的语法糖,当'i'是可变的时语法糖用于'{i = ref 42}',那么浅拷贝将复制ref单元。我无法找到指定可变记录字段是否是不可变指针的不可变指针,该指针位于记录之外的文档部分。 –

+4

@Mike:在OCaml中,'t ref'是'{mutable contents:t}'的糖(如手册某处所述),所以您可以放心地假定'mutable'没有通过'ref '。 ;) –

+0

@AndreasRossberg,太好了。 “可变”记录字段是构建其他抽象的可变存储原语。非常感谢。为了记录,手册参考是[2。2 Mutable](http://caml.inria.fr/pub/docs/u3-ocaml/ocaml-core.html#mutable),其中说:“事实上,在OCaml中,引用不是原始的:它们是可变的特殊情况记录。”并且在[Pervasives ocamldoc](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html#TYPEref)中重申了这一点。 –