Gre*_*bet 1 ocaml garbage-collection internals
根据关于Rosetta Code (源代码)的部分,OCaml元组(当由函数返回时)保持活动或作为一个单元收集.
元组的空间安全
OCaml程序员应该知道,当使用元组返回多个值时,终结不会独立处理每个值,而是作为整体处理元组.因此,只有当所有值都不可达时,才会最终确定所有值.
我想知道在OCaml 4.05中是否仍然如此,以及是否有任何其他方法可以获得不具有此属性的产品类型的相同功能.
你提到的文字和例子都是误导性的.如果您投影并仅保留其中一个组件,则您的元组及其组件将不会在程序的整个生命周期内保留.
它们最多只保留在let元组的解构绑定范围内,而且通常是短暂的.我个人从未发现这在实践中是一个问题.
为了证明这一点,如果你稍微调整一下例子:
let pair a b =
let ra = Array.make 1 a
and rb = Array.make 1 b in
let f r = Printf.printf "> finalised: %d\n%!" r.(0) in
Gc.finalise f ra;
Gc.finalise f rb;
(ra, rb)
let a =
let a, _ = pair 1 2 in
let _, _ = pair 3 4 in
a
let () =
Gc.full_major (); (* garbage collection *)
Printf.printf "Used: %d\n%!" a.(0)
Run Code Online (Sandbox Code Playgroud)
您将看到除a收集垃圾之外的所有内容.Toplevel定义也会正确地收集垃圾:
let e, _ = pair 5 6
let () = Gc.full_major ()
Run Code Online (Sandbox Code Playgroud)
此外,Leo White向我指出,我上面描述的是最糟糕的情况.如果a原始示例中的表达式在表达式中被多次使用,那么其他组件将被gc'd.当a只使用一次时,OCaml不会从元组投射它直到真正需要 - 例如,如果投影是在一个if我们可能永远不需要为投影完成的工作.此优化可能会延长值的生命周期,但绝不会超出其原始范围.