2016-11-16 5 views
4

Beide erreichen die gleiche SacheOCaml lazy evaluation: 'a lazy_t vs unit ->' a

# 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 

Gibt es einen Grund sollte man über den anderen bevorzugt werden? Welche ist effizienter?

Antwort

7

Zuerst verhalten sie sich nicht gleich, versuchen, Lazy.force y noch ein Mal zu tun, und Sie werden den Unterschied feststellen, die "World" Nachricht wird nicht mehr gedruckt, so dass die Berechnung nicht wiederholt wird, da das Ergebnis in Erinnerung war im faulen Wert.

Dies ist der Hauptunterschied zwischen Lazy-Berechnungen und Thunks. Beide verzögern die Berechnung bis zu dem Zeitpunkt, zu dem sie gezwungen werden. Aber der Thunk wird seinen Körper jedes Mal auswerten, wenn der Lazy-Wert einmal ausgewertet wird und das Ergebnis der Berechnung protokolliert wird.

Unter der Haube ist der Lazy-Wert als Thunk-Objekt mit einem speziellen Flag implementiert. Wenn Runtime zuerst den Lazy-Wert aufruft, ersetzt sie den Körper des Thunk durch das Ergebnis der Berechnung. Nach dem ersten Aufruf an Lazy.force y wurde das Objekt y tatsächlich zu einer Ganzzahl 2. Also die konsequenten Aufrufe an Lazy.force nichts tun.

2

Lazy.force gibt denselben Wert erneut zurück, ohne erneut zu berechnen.

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 
Verwandte Themen