OCaml产品类型,每个元素具有独立的可达性

时间:2017-10-28 02:28:29

标签: garbage-collection ocaml internals

根据Rosetta Code (source)的一节,OCaml元组(由函数返回时)保持活动或作为一个整体收集。

  

元组的空间安全

     

OCaml程序员应该意识到这一点   当使用元组返回多个值时,最终确定   不能独立处理每个值,而是将元组作为a处理   整个。因此,只有在所有值都完成时才会最终确定所有值   再也找不到了。

我想知道在OCaml 4.05中是否仍然如此,以及是否有任何其他方法可以获得不具备此属性的产品类型的相同功能。

2 个答案:

答案 0 :(得分:5)

您提到的文字和示例具有误导性。如果您投影并仅保留其中一个组件,则您的元组及其组件将不会在程序的整个生命周期内保留。

它们只会在元组的解构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)

您将看到除a之外的所有内容都会被垃圾回收。 Toplevel定义也会正确地收集垃圾:

let e, _ = pair 5 6
let () = Gc.full_major ()

此外,Leo White向我指出,我上面描述的是最糟糕的情况。如果原始示例中的a在表达式中多次使用,则其他组件将被gc'd。当a仅使用一次时,OCaml不会将其从元组投射到真正需要 - 例如,如果投影是在if下完成的,我们可能永远不需要为此工作投影。此优化可能会延长值的生命周期,但绝不会超出其原始范围。

答案 1 :(得分:3)

我不是OCaml GC的专家,但如果这方面的情况有所改变,我会感到非常惊讶。

可能具有您想要的行为的一种可能性是来自Weak module的弱数组。

以下是类型'a Weak.t的简介:

  

弱指针数组的类型(弱数组)。弱指针是垃圾收集器可以在程序不再使用该值(通过正常指针)时擦除的值。

弱数组将具有相同类型的元素。如果你需要不同的类型,我想你可能有一个长度为1的弱数组元组。弱数组中的值将被独立地垃圾收集。但是,元组本身将保留,直到所有数组都为空。