Reference 在OCaml中复制构造?

Reference 在OCaml中复制构造?,reference,copy,ocaml,Reference,Copy,Ocaml,OCaml值通过引用传递,而不是通过值传递。当值为常数时,参考值和值之间没有明显差异。但是,当值是可变的(例如具有可变字段的结构)时,我可能希望复制它,以便当一个变量改变值时,设置为前一个变量的另一个变量也不会改变。我可以在OCaml中执行此操作吗?恐怕没有自动简便的方法。您必须通过自己编写一些代码来复制一个值。比如说, type t = { x : int option; mutable y : int option } let copy t = { t with x = t.x } le

OCaml值通过引用传递,而不是通过值传递。当值为常数时,参考值和值之间没有明显差异。但是,当值是可变的(例如具有可变字段的结构)时,我可能希望复制它,以便当一个变量改变值时,设置为前一个变量的另一个变量也不会改变。我可以在OCaml中执行此操作吗?

恐怕没有自动简便的方法。您必须通过自己编写一些代码来复制一个值。比如说,

type t = { x : int option; mutable y : int option }

let copy t = { t with x = t.x }

let () =
  let t = { x = None; y = Some 1 } in
  let t' = copy t in
  t.y <- None;
  assert (t'.y <> None) (* check t'.y is not shared *)
type t={x:int-option;可变y:int-option}
让我们复制t={t和x=t.x}
让()=
设t={x=None;y=some1}in
让t'=将t复制进来

t、 y引入可变值有三种语法方法:

  • 定义具有可变字段的记录
  • 使用一些预定义的可变容器,如Array、Bytes、Bigarray
  • 定义一个具有可变字段的类
一个函数可以
克隆它们
除非您愿意依赖不安全的
Obj
模块或使用
Marshal
模块,否则不存在这样的函数,它将接受任何值并返回其克隆。因此,在纯OCaml中,不可能获得另一个值的逐位拷贝,因为OCaml试图从应用程序中抽象其二进制表示。如果您确实需要,那么以下低效的实施可能足以满足您的需要:

   let clone (type t) (x : t) : t = 
     let buf = Marshal.(to_bytes x [No_sharing; Closures]) in
     Marshal.from_bytes buf 0
它不适用于不支持封送的值,例如文件描述符,以及不实现封送接口的自定义对象(用C实现)

可变记录 没有所有记录都属于的基类型。因此,对于每个具有可变类型的记录,您需要提供自己的克隆器,或者您可以依赖上面的
clone
函数

预定义容器 所有预定义的容器都提供克隆函数,但是,由于它们都属于不同的类型,因此没有通用函数来处理它们

可变对象
面向对象编程总是与可变性紧密相连。因此,OCaml提供了适用于所有对象的
Oo.copy
函数,因为所有其他对象都属于一种对象类型
。因此,如果您确实需要一个通用的克隆函数,那么考虑使用对象。 谢谢!在with构造中,复制值的字段是否指向堆上的相同位置,或者它们是否保证引用其他内容?如果是这样,“x=t.x”步骤是否是一种优化,以使不可变字段指向同一堆位置?是否确定Obj.dup是递归的?没有文档,obj.c中caml_obj_dup中的代码似乎不是递归的。