|
|
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.