Lazy.lazy_from_val
的文档声明此函数适用于特殊情况:
val lazy_from_val : 'a -> 'a t
lazy_from_val v returns an already-forced suspension of v This is for special purposes only and should not be confused with lazy (v).
他们在谈论哪些案例?
如果我从以下值创建一对暂停计算:
let l1 = lazy 123
let l2 = Lazy.lazy_from_val 123
这两者有什么区别?因为Lazy.lazy_is_val l1
和Lazy.lazy_is_val l2
都返回 true ,表示该值已被强制执行!
答案 0 :(得分:7)
如果您需要一个惰性值,但有时会有一个已经计算过的(非惰性)值。您可以使用lazy_from_val
将已计算的值转换为值的(强制)延迟版本。
let f lazyint =
Lazy.force lazyint + 42
let li = lazy 4;;
# f li;;
- : int = 46
# f 14;;
^^
Error: This expression has type int but an expression was expected of type
int Lazy.t = int lazy_t
# f (Lazy.lazy_from_val 14);;
- : int = 56
在这个(人为的)示例中,您可能希望使用普通整数值(在此示例中为14)调用f
。您可以这样做,但您需要使用Lazy.lazy_from_val
才能使其正常运行。
关键区别在于lazy
采用类型'a
的表达式,并创建类型为'a lazy_t
的暂停计算(实质上是闭包)。 Lazy.lazy_from_val
采用类型为'a
的预先计算的值,并将其转换为类型为'a lazy_t
的(预强制)值。如果表达式有副作用,可以看出两者之间的差异。
# let p () = print_string "here\n"; 3 ;;
val p : unit -> int = <fun>
# let l1 = lazy (p ());;
val l1 : int lazy_t = <lazy>
# let l2 = Lazy.lazy_from_val (p ());;
here
val l2 : int Lazy.t = lazy 3
# f l1;;
here
- : int = 45
# f l2;;
- : int = 45
#
您可以使用显式闭包和引用直接实现延迟操作。正如Matthias Benkard指出的那样,OCaml的惰性机制使用特殊语法来减少使用它的麻烦。即,lazy
是OCaml关键字,而不是函数。
答案 1 :(得分:2)
lazy_from_val
是函数而不是语法。因此,
# let id = fun x -> x;;
val id : 'a -> 'a = <fun>
# Lazy.lazy_is_val (lazy (id 123));;
- : bool = false
# Lazy.lazy_is_val (Lazy.lazy_from_val (id 123));;
- : bool = true