|
|
1.1 root 1: (* Generators and Iterators *)
2:
3: exception DONE
4:
5: (* An arithmetic range generator: numbers from n upto (or downto) m *)
6: infix to;
7: fun (n:int) to (m:int) =
8: let val dir = if n<=m then 1 else ~1;
9: val pos = ref(n-dir);
10: val test = if n<=m then (fn () => !pos>m) else (fn () => !pos<m)
11: in (fn () => (pos := !pos+dir;
12: if test() then raise DONE else !pos))
13: end
14:
15: (* Exercise: generalize this to take a step parameter. *)
16:
17:
18: (* A list generator: generates elements of a list in succession *)
19: fun over l =
20: let val rest = ref l
21: in fn () => case !rest
22: of [] => raise DONE
23: | x::l => (rest:=l; x)
24: end
25:
26:
27: (* A loop iterator *)
28: fun loop gen f = (f(gen ()); loop gen f) handle DONE => ()
29:
30: (* A collect iterator -- collects results in a list *)
31: fun collect gen f = f(gen())::(collect gen f) handle DONE => [];
32:
33:
34: (* examples *)
35: loop (3 to 5) (fn (n:int) => print((makestring n)^"\n"));
36:
37: collect (3 to 5) (fn n => n*n);
38:
39: fun sq (x:int) = x*x;
40: collect (over [1,2,3]) sq;
41:
42:
43: (* Exercises:
44: 1. Define iterators over pairs of generators.
45: 2. Define a generator that produces the first n elements of a stream.
46: 3. Define a function that maps generators to streams.
47: 4. Define a binary tree type and generators that traverse trees.
48: 5. Try to think of some other interesting iterators beside "loop" and
49: "collect".
50: *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.