从我到目前为止观察到的情况来看,具有可变字段的记录就好像它们总是通过引用传递一样。例如,如果我将记录传递给某个函数或将其存储在数据结构中,则该记录不会在该过程中被复制。例如,此代码:
type t = {
mutable t_val: int
}
let () =
let ht = Hashtbl.create 16 in
let x = { t_val = 42 } in
Hashtbl.replace ht "x" x;
x.t_val <- 43;
let x2 = Hashtbl.find ht "x" in
Format.printf "x.t_val: %d, x2.t_val: %d@." x.t_val x2.t_val
输出
x.t_val: 43, x2.t_val: 43
这是一种可靠的预期行为还是取决于具体情况?
答案 0 :(得分:2)
是的,它是可靠的和有意的。事实上,不仅可变记录通过引用传递,一切都是。只有使用不可变数据,您才会发现差异。 (有一个例外:像int
这样的小型不可变数据经过优化,可以按值传递方式进行处理。但是,从语义上讲,你可以放心地假设一切都像是一直通过参考一样工作。)
答案 1 :(得分:0)
这与传值或传递引用无关。例如,Java只传递值,当您传递引用时,在函数内部,它们还可以修改引用所指向的对象的字段,并且这些更改对于引用该引用的任何其他人都是可见的。对象
(传递值和传递引用之间的区别在于当您直接将分配给参数变量(不访问指向它的对象或其他任何内容)时发生的情况函数;在pass-by-value中,它对调用范围中传递的变量没有影响;在pass-by-reference中,它与调用范围中传递的变量的赋值具有相同的效果。在OCaml中,它在初始化之后不可能直接分配给变量(根本就没有这样做的语法),因此,传值和传递引用之间没有区别。)
你所说的是记录类型是引用类型,即记录类型的值实际上是对底层结构的引用,多个引用可以指向相同的底层结构,并且可以看到通过一个引用的修改通过对同一底层结构的其他引用。这是真的。正如@kne所提到的,OCaml中唯一没有&#34;盒装&#34;的类型,即引用类型,是简单的不可变类型,如int
或可以适合int
的东西,因为它们是不可变的,所以它们是引用类型还是值类型(除了==
之类的语义之外)几乎没有区别。