2016-11-16 2 views
4

И достичь того жеOCaml ленивой оценки: «а lazy_t против единицы ->» а

# let x = fun() -> begin print_endline "Hello"; 1 end;; 
val x : unit -> int = <fun> 
# x();; 
Hello 
- : int = 1 
# let y = lazy begin print_endline "World"; 2 end;; 
val y : int lazy_t = <lazy> 
# Lazy.force y;; 
World 
- : int = 2 

Есть ли какая-либо причина один должно быть предпочтительнее, чем другие? Какой из них эффективнее?

ответ

7

Прежде всего, они не ведут себя одинаково, попробуйте сделать еще Lazy.force y еще раз, и вы заметите разницу, сообщение "World" больше не печатается, поэтому вычисление не повторяется, так как результат был запомнен в ленивом значении.

Это основное различие между ленивыми вычислениями и thunks. Они оба откладывают вычисления до момента, когда они вынуждены. Но thunk будет оценивать свое тело каждый раз, когда значение lazy будет оцениваться один раз, и результат вычисления будет запомнен.

Под капюшоном ленивое значение реализуется как объект-объект со специальным флагом. Когда среда выполнения сначала вызывает ленивое значение, она заменяет тело thunk результатом вычисления. Итак, после первого вызова Lazy.force y объект y фактически стал целым числом 2. Поэтому последующие звонки в Lazy.force ничего не делают.

2

Lazy.force возвращает то же значение снова, не переучивая его.

Exemple

let ra = ref 0 ;; 
let y = lazy (ra:= !ra+1);; 
Lazy.force y;; 
# Lazy.force y;; 
- : unit =() 
# !ra;; 
- : int = 1 
# Lazy.force y;; 
- : unit =() 
# !ra;; 
- : int = 1 
Смежные вопросы