Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / src / Lazy.adoc
1 Lazy
2 ====
3
4 In a lazy (or non-strict) language, the arguments to a function are
5 not evaluated before calling the function. Instead, the arguments are
6 suspended and only evaluated by the function if needed.
7
8 <:StandardML:Standard ML> is an eager (or strict) language, not a lazy
9 language. However, it is easy to delay evaluation of an expression in
10 SML by creating a _thunk_, which is a nullary function. In SML, a
11 thunk is written `fn () => e`. Another essential feature of laziness
12 is _memoization_, meaning that once a suspended argument is evaluated,
13 subsequent references look up the value. We can express this in SML
14 with a function that maps a thunk to a memoized thunk.
15
16 [source,sml]
17 ----
18 signature LAZY =
19 sig
20 val lazy: (unit -> 'a) -> unit -> 'a
21 end
22 ----
23
24 This is easy to implement in SML.
25
26 [source,sml]
27 ----
28 structure Lazy: LAZY =
29 struct
30 fun lazy (th: unit -> 'a): unit -> 'a =
31 let
32 datatype 'a lazy_result = Unevaluated of (unit -> 'a)
33 | Evaluated of 'a
34 | Failed of exn
35
36 val r = ref (Unevaluated th)
37 in
38 fn () =>
39 case !r of
40 Unevaluated th => let
41 val a = th ()
42 handle x => (r := Failed x; raise x)
43 val () = r := Evaluated a
44 in
45 a
46 end
47 | Evaluated a => a
48 | Failed x => raise x
49 end
50 end
51 ----