etng-r2/clojure-sequences-20100416.txt
changeset 285 034958cf32d9
equal deleted inserted replaced
284:1bf8431909d4 285:034958cf32d9
       
     1 Subject: Clojure's sequences and nil punning
       
     2 Time-stamp: <2010-04-16 17:25:01 tonyg>
       
     3 From: tonyg
       
     4 
       
     5 http://clojure.org/lazy
       
     6 
       
     7     namespace s = "http://eighty-twenty.org/etng/r1/ns/stream#";
       
     8     define s:foldr stream knil kons ->
       
     9       stream .s:case {
       
    10 	.s:empty -> knil;
       
    11 	.s:next(head, tail) -> kons(head, s:foldr tail knil kons);
       
    12       };
       
    13     define s:map stream fn -> s:foldr stream s:empty {elt, acc -> s:cons(fn(elt), acc)};
       
    14 
       
    15 Expand through `s:foldr`, and we get
       
    16 
       
    17     define s:map stream fn ->
       
    18       stream .s:case {
       
    19       	.s:empty -> s:empty;
       
    20 	.s:next(head, tail) -> s:cons(fn(head), s:map tail fn);
       
    21       };
       
    22 
       
    23 Delay:
       
    24 
       
    25     define nothing = { .case v -> v .nothing };
       
    26     define just x  = { .case v -> v .just x };
       
    27 
       
    28     define delay v ->
       
    29       -- Carefully written to avoid holding onto v for too long.
       
    30       -- Needs let rec cell = etc. to avoid the initial cell.set!
       
    31       let cell = ref ();
       
    32       do cell.set { let forced = v ();
       
    33       	       	    do cell.set { forced };
       
    34 		    forced };
       
    35       { msg -> cell.get () msg };
       
    36 
       
    37 Lazy map:
       
    38 
       
    39     define s:lazymap stream fn ->
       
    40       delay {stream .s:case {
       
    41       	.s:empty -> s:empty;
       
    42 	.s:next(head, tail) = s:cons(delay {fn(head)}, delay {s:map tail fn});
       
    43       }};