Какова цель Lazy.lazy_from_val OCaml? - PullRequest
5 голосов
/ 18 марта 2012

В документе 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 , говоря, что значение уже принудительно!

Ответы [ 2 ]

7 голосов
/ 18 марта 2012

Специальное назначение будет, если вам нужно ленивое значение, но иногда у вас уже есть вычисленное (не ленивое) значение. Вы можете использовать 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, а не функция.

2 голосов
/ 18 марта 2012

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
...