Es gibt etwas Magie im ocaml Lazy-Typ. Ich denke, es ist einfacher, Faulheit zu verstehen, wenn Sie es selbst implementieren, was einfach, aber nicht so syntaktisch bequem ist. Die Tricks sind
- Verzögerung Auswertung Schließungen
- Verwendung ref Zellen unter Verwendung von Berechnungen memoize
Hier ist es klar, wie und wann die memoization geschieht während Lazy'.force.
module Lazy' : sig
type 'a t
val delay: (unit -> 'a) -> 'a t
val force: 'a t -> 'a
end = struct
type 'a susp =
| NotYet of (unit -> 'a)
| Done of 'a
type 'a t = 'a susp ref
let delay f = ref (NotYet f)
let force f =
match !f with
| Done x -> x
| NotYet f' ->
let a = f'() in
f := Done a;
a
end
Typ 'a stream = Nachteile von' a * 'ein Stream Lazy'.t ;;
lassen diejenigen = rec ones'() = Cons (1, Lazy'.delay ones ') in Einsen'() lassen ;;
Lassen Sie die Karte fs = match s mit | Nachteile (h, t) -> Nachteile (f h, Lazy'.delay (Spaß() -> Karte f (Lazy'.force t))) ;;
Was ist der Zweck der zweiten Indirektion bei 'Typ 'a t = Einheit ->' ein Susp Ref '? Sie geben nur 'fun() -> r' zurück oder wenden' 'let s = f() in' an. Warum kannst du den Mittelsmann nicht schneiden? PS: Um klar zu sein, ich frage, warum http://ideone.com/Eidm34 nicht funktionieren würde. –
Einverstanden. Es ist unnötig. Wir sollten "a t = 'a susp ref" eingeben. Die Indirektion ist ein Rest von einem früheren Versuch :) – seanmcl