2012-03-18 3 views
5

Док из Lazy.lazy_from_val утверждает, что эта функция для особых случаев:Какова цель OCZLL 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 говорят, что значение уже принудительно!

ответ

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 

В этом (надуманный) Например, вы можете захотеть назвать 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, а не функция.

+0

Спасибо за объяснение! – Ricardo

+1

«Ленивый механизм OCaml использует специальный синтаксис» ... и специальные функции GC, чтобы удалить косвенность, став бесполезными для принудительных значений. –

+0

Действительно приятно знать, спасибо! (Есть ли хорошая ссылка для этого?) –

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 
Смежные вопросы