Специальное назначение будет, если вам нужно ленивое значение, но иногда у вас уже есть вычисленное (не ленивое) значение. Вы можете использовать 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
В этом (надуманном) примере вы можете вызвать f
с обычным целочисленным значением (14 в этом примере). Вы можете сделать это, но вам нужно использовать 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
#
Вы можете реализовать ленивые операции напрямую, используя явные замыкания и ссылки. Как указывает Матиас Бенкард, ленивый механизм OCaml использует специальный синтаксис, чтобы с ним было менее громоздко работать. Т.е., lazy
- это ключевое слово OCaml, а не функция.