Специальной целью будет, если вам нужно ленивое значение, но иногда есть уже вычисленный (не ленивое) значение. Вы можете использовать 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 использует специальный синтаксис, чтобы сделать его менее громоздким для работы. I.e., lazy
- это ключевое слово OCaml, а не функция.
Спасибо за объяснение! – Ricardo
«Ленивый механизм OCaml использует специальный синтаксис» ... и специальные функции GC, чтобы удалить косвенность, став бесполезными для принудительных значений. –
Действительно приятно знать, спасибо! (Есть ли хорошая ссылка для этого?) –