每个元素具有独立可达性的 OCaml 产品类型
OCaml Product type with independent reachability for each element
根据 Rosetta 代码 (source) 的部分,OCaml 元组(当由函数返回时)保持活动状态或作为一个单元收集。
Space safety of tuples
The OCaml programmer should be aware that
when multiple values are returned with a tuple, the finalisation does
not handle each values independently, but handles the tuple as a
whole. So all the values are only finalised when all the values are
not reachable anymore.
我想知道这在 OCaml 4.05 中是否仍然适用,以及是否有任何其他方法可以获得与没有此功能的产品类型相同的功能 属性。
我不是 OCaml GC 方面的专家,但如果这方面发生了变化,我会感到非常惊讶。
可能具有您想要的行为的一种可能性是弱数组,来自 Weak module。
这里是 'a Weak.t
类型的概要:
The type of arrays of weak pointers (weak arrays). A weak pointer is a value that the garbage collector may erase whenever the value is not used any more (through normal pointers) by the program.
弱数组将包含相同类型的元素。如果你需要不同的类型,我想你可以有一个长度为 1 的弱数组元组。弱数组中的值将被独立地垃圾收集。但是,元组本身会一直存在,直到所有数组都为空。
您提到的文字和示例具有误导性。如果您仅投影并保留其组件之一,则您的元组及其组件将不会在程序的生命周期内保留。
它们只会在元组的解构 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
之外的所有内容都会被垃圾回收。顶级定义也将正确收集垃圾:
let e, _ = pair 5 6
let () = Gc.full_major ()
而且 Leo White 向我指出,我上面描述的是最坏的情况。如果原始示例中的 a
在表达式中多次使用,则其他组件将被 gc'd。当 a
仅使用一次时,OCaml 不会从元组中投影它,直到真正需要它——例如,如果投影是在 if
下完成的,我们可能永远不需要为投影。这种优化可能会延长值的生命周期,但绝不会超出其原始范围。
根据 Rosetta 代码 (source) 的部分,OCaml 元组(当由函数返回时)保持活动状态或作为一个单元收集。
Space safety of tuples
The OCaml programmer should be aware that when multiple values are returned with a tuple, the finalisation does not handle each values independently, but handles the tuple as a whole. So all the values are only finalised when all the values are not reachable anymore.
我想知道这在 OCaml 4.05 中是否仍然适用,以及是否有任何其他方法可以获得与没有此功能的产品类型相同的功能 属性。
我不是 OCaml GC 方面的专家,但如果这方面发生了变化,我会感到非常惊讶。
可能具有您想要的行为的一种可能性是弱数组,来自 Weak module。
这里是 'a Weak.t
类型的概要:
The type of arrays of weak pointers (weak arrays). A weak pointer is a value that the garbage collector may erase whenever the value is not used any more (through normal pointers) by the program.
弱数组将包含相同类型的元素。如果你需要不同的类型,我想你可以有一个长度为 1 的弱数组元组。弱数组中的值将被独立地垃圾收集。但是,元组本身会一直存在,直到所有数组都为空。
您提到的文字和示例具有误导性。如果您仅投影并保留其组件之一,则您的元组及其组件将不会在程序的生命周期内保留。
它们只会在元组的解构 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
之外的所有内容都会被垃圾回收。顶级定义也将正确收集垃圾:
let e, _ = pair 5 6
let () = Gc.full_major ()
而且 Leo White 向我指出,我上面描述的是最坏的情况。如果原始示例中的 a
在表达式中多次使用,则其他组件将被 gc'd。当 a
仅使用一次时,OCaml 不会从元组中投影它,直到真正需要它——例如,如果投影是在 if
下完成的,我们可能永远不需要为投影。这种优化可能会延长值的生命周期,但绝不会超出其原始范围。