module Lazy:sig
..end
延遲計算。
type'a
t ='a CamlinternalLazy.t
類型為 'a Lazy.t
的值是一個延遲的計算,稱為暫停 (suspension),其結果的類型為 'a
。特殊的表達式語法 lazy (expr)
會建立一個對 expr
計算的暫停,但不會立即計算 expr
本身。 「強制 (forcing)」暫停將會計算 expr
並返回其結果。使用特殊的模式語法 lazy(pattern)
匹配暫停也會計算底層的表達式,並嘗試將其綁定到 pattern
。
let lazy_option_map f x =
match x with
| lazy (Some x) -> Some (Lazy.force f x)
| _ -> None
注意:如果惰性模式出現在模式匹配的多個情況中,即使在最終由模式匹配選定的情況之外,也可能會強制執行惰性表達式。在上面的範例中,暫停 x
總是會被計算。
注意:lazy_t
是編譯器用於 lazy
關鍵字的內建類型建構子。您不應直接使用它。請始終使用 Lazy.t
來代替。
注意:Lazy.force
並非並發安全 (concurrency-safe)。如果您在多個纖程 (fibers)、系統線程 (systhreads) 或域 (domains) 中使用此模組,則需要新增一些鎖定。然而,該模組可確保記憶體安全,因此並發存取此模組不會導致崩潰,但行為未指定。
注意:如果程式使用 -rectypes
選項編譯,則類型檢查器會接受以下形式的病態遞迴定義:let rec x = lazy x
或 let rec x = lazy(lazy(...(lazy x)))
,並且在強制執行時會導致病態值,從而在垃圾回收器和執行時系統的其他部分觸發無限迴圈。如果沒有 -rectypes
選項,此類病態遞迴定義將會被類型檢查器拒絕。
exception Undefined
當從多個纖程、系統線程或域並發強制執行暫停時,或者當暫停嘗試遞迴強制執行自身時,會引發此例外。
val force : 'a t -> 'a
force x
會強制執行暫停 x
並返回其結果。如果 x
已經被強制執行,Lazy.force x
會再次返回相同的值,而不會重新計算。如果它引發了一個例外,則會再次引發相同的例外。
Undefined
(請參閱 Lazy.Undefined
)。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
已經被強制執行時,此行為會節省暫停的建構,但另一方面,它會執行更多可能會無用的積極工作 (eager work),如果您永遠不強制執行函數結果。
如果 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 f
與 lazy (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
。
x
嘗試遞迴強制執行 x
本身,則引發 Undefined
。Undefined
(請參閱 Lazy.Undefined
)。