W lamzie typu ocaml jest trochę magii. Wydaje mi się, że łatwiej jest zrozumieć lenistwo, kiedy sam je implementujesz, co jest łatwe, ale nie tak wygodne pod względem składniowym. Sztuczki są
- ocena opóźnienie przy użyciu zamknięć
- komórki wykorzystują wg memoize obliczeń
Tutaj jest jasne, w jaki sposób i kiedy memoization dzieje podczas 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
wpisz "strumień = Wady" a * "strumień Lazy'.t ;;
pozwolić te = pozwolić ones rec() = (1, Wady Lazy'.delay ones ') w te'() ;;
let rec map f s = mecz s z | Wady (h, t) -> Wady (f h, Lazy'.delay (fun() -> map f (Lazy'.force t))) ;;
Jaki jest cel drugiego kierunku w "typie" a t = jednostka -> "a susp ref"? Zwracasz tylko 'fun() -> r' lub stosując' 'let s = f() in'. Dlaczego nie możesz przeciąć pośrednika? PS: jasne, pytam, dlaczego http://ideone.com/Eidm34 nie zadziała. –
Uzgodnione. To niepotrzebne. Powinniśmy napisać '' a t = 'a susp ref'. Indywidualność jest szczątkowa od wcześniejszej próby :) – seanmcl