Ocaml 可变记录字段和{x with…}

Ocaml 可变记录字段和{x with…},ocaml,record,semantics,mutable,Ocaml,Record,Semantics,Mutable,我一直在阅读ocaml文档,但我无法解释{x with…}如何处理可变字段。警察说 6.7表达 记录 表达式{expr with field1=expr1;…;fieldn=exprn}构建一个新记录,其中字段field1…fieldn等于expr1…exprn,所有其他字段的值与记录expr中的值相同。换句话说,它返回记录expr的浅拷贝,除了初始化为expr1…exprn的字段field1…fieldn 这种“浅拷贝”的说法可以解释为,mutable未提及的字段共享存储空间或可能引用嵌套记

我一直在阅读
ocaml
文档,但我无法解释
{x with…}
如何处理可变字段。警察说

6.7表达

记录 表达式
{expr with field1=expr1;…;fieldn=exprn}
构建一个新记录,其中
字段field1…fieldn
等于
expr1…exprn
,所有其他字段的值与记录
expr
中的值相同。换句话说,它返回记录
expr
浅拷贝,除了初始化为
expr1…exprn
的字段
field1…fieldn

这种“浅拷贝”的说法可以解释为,
mutable
未提及的字段共享存储空间或可能引用嵌套记录。当我测试(使用“OCaml顶级,版本4.00.1”)时

这让我非常高兴,但我想确保

{ 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
来支持,而不是分配新的可变存储。

在我所看到的任何地方,“浅拷贝”意味着,只要像赋值一样将所有组件转移,即使在所有字段都是可变的语言中,如Java。所以在这个例子中,
(让tmp=e在{f0=tmp.f0;..fi-1=tmp.fi-1;fi=x;fi+1=tmp.fi+1;..fn=tmp.fn})
正是它的意思。

所以你只需要我们确认,
{e with fi=x}
的有效语法糖(让tmp=e在{f0=tmp.f0;..fi fi 1=tmp.fi 1;fi=x;fi
…等等?@RobertHarvey,一个指向其他文档的指针或一个如何阅读这些文档的解释会很有帮助,但是任何来自知道什么是未定义行为和什么不是未定义行为的人的东西都会有所帮助。如果
mutable
使用
ref
实现为语法糖,那么
{mutable i:int}
就是
的语法糖{i:int-ref}
{i=42}
i
可变时,是
{i=ref 42}的语法糖
,则浅层副本将复制ref单元格。我找不到文档中指定可变记录字段是否是指向位于记录外部的可别名
ref
的不可变指针的部分。@Mike:在OCaml中,
t ref
{mutable contents:t}
的糖(如手册中某处所述),因此您可以放心地假设,
mutable
不是通过
ref
间接定义的;)@AndreasRossberg,太好了。
mutable
记录字段是构建其他抽象的可变存储原语。非常感谢。对于记录,手动参考是“事实上,在OCaml中,引用并不是原始的:它们是可变记录的特例。”这一点在文章中得到了重申。
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 })