模块 Stdlib.Lazy

module Lazy: Lazy

type 'a t = 'a CamlinternalLazy.t 

类型为 'Lazy.t 的值是一个延迟计算,称为挂起,其结果类型为 'a。特殊的表达式语法 lazy (expr) 创建计算 expr 的挂起,但不会立即计算 expr 本身。“强制”挂起将计算 expr 并返回其结果。使用特殊模式语法 lazy(pattern) 匹配挂起也会计算底层表达式并尝试将其绑定到 pattern

      let lazy_option_map f x =
      match x with
      | lazy (Some x) -> Some (Lazy.force f x)
      | _ -> None
    

注意:如果延迟模式在模式匹配的多个情况下出现,则即使在最终由模式匹配选择的 case 之外,也可能会强制执行延迟表达式。在上面的示例中,挂起 x 始终会被计算。

注意:lazy_t 是编译器为 lazy 关键字使用的内置类型构造函数。您不应直接使用它。始终使用 Lazy.t 代替。

注意:Lazy.force 不是并发安全的。如果您将此模块与多个纤程、系统线程或域一起使用,则需要添加一些锁。但是,该模块确保内存安全,因此,并发访问此模块不会导致崩溃,但行为未指定。

注意:如果程序使用 -rectypes 选项编译,则形式为 let rec x = lazy xlet rec x = lazy(lazy(...(lazy x))) 的不合理的递归定义会被类型检查器接受,并在强制时导致不正确的,触发垃圾回收器和运行时系统其他部分中无限循环的值。在没有 -rectypes 选项的情况下,此类不合理的递归定义会被类型检查器拒绝。

exception Undefined

当从多个纤程、系统线程或域并发强制挂起,或当挂起尝试递归强制自身时引发。

val force : 'a t -> 'a

force x 强制挂起 x 并返回其结果。如果 x 已经被强制,则 Lazy.force x 会再次返回相同的值,而无需重新计算它。如果它引发了异常,则会再次引发相同的异常。

迭代器

val map : ('a -> 'b) -> 'a t -> 'b t

map f x 返回一个挂起,当强制时,它会强制 x 并将其值应用于 f

它等价于 lazy (f (Lazy.force x))

已强制挂起的推理

val is_val : 'a t -> bool

is_val x 如果 x 已经被强制并且没有引发异常,则返回 true

val from_val : 'a -> 'a t

from_val v 首先计算 v(与任何函数一样)并返回其结果的已强制挂起。它与 let x = v in lazy x 相同,但在某些情况下使用动态测试来优化挂起创建。

val map_val : ('a -> 'b) -> 'a t -> 'b t

map_val f x 如果 x 已经被强制,则直接应用 f,否则其行为与 map f x 相同。

x 已经被强制时,此行为可以节省挂起的构造,但另一方面,它会更积极地执行更多工作,如果您从未强制函数结果,则这些工作可能没有用。

如果 f 引发了异常,它将在 is_val x 时立即引发,或者仅在强制 thunk 时引发。

如果 map_val f x 没有引发异常,则 is_val (map_val f x) 等于 is_val x

高级

以下定义仅供高级使用;它们需要熟悉延迟编译方案才能正确使用。

val from_fun : (unit -> 'a) -> 'a t

from_fun flazy (f ()) 相同,但效率略高。

仅当函数 f 已定义时才应使用它。特别是,编写 from_fun (fun () -> expr) 始终不如编写 lazy expr 效率高。

val force_val : 'a t -> 'a

force_val x 强制挂起 x 并返回其结果。如果 x 已经被强制,则 force_val x 会再次返回相同的值,而无需重新计算它。

如果 x 的计算引发了异常,则 force_val x 是否引发相同的异常或 Lazy.Undefined 未指定。