etng-r2/clojure-sequences-20100416.txt
author Tony Garnock-Jones <tonygarnockjones@gmail.com>
Tue, 25 May 2010 08:09:57 +1200
changeset 285 034958cf32d9
permissions -rw-r--r--
Notes and incomplete work. -rw-r--r-- 1 tonyg staff 3935 Aug 11 2009 boot.tng-modules -rw-r--r-- 1 tonyg staff 454 Aug 9 2009 calc.tng -rw-r--r-- 1 tonyg staff 1214 Apr 16 18:18 clojure-sequences-20100416.txt -rw-r--r-- 1 tonyg staff 2265 Feb 24 13:20 monadic-book.tng -rw-r--r-- 1 tonyg staff 290 Dec 29 19:37 things-to-consider.txt

Subject: Clojure's sequences and nil punning
Time-stamp: <2010-04-16 17:25:01 tonyg>
From: tonyg

http://clojure.org/lazy

    namespace s = "http://eighty-twenty.org/etng/r1/ns/stream#";
    define s:foldr stream knil kons ->
      stream .s:case {
	.s:empty -> knil;
	.s:next(head, tail) -> kons(head, s:foldr tail knil kons);
      };
    define s:map stream fn -> s:foldr stream s:empty {elt, acc -> s:cons(fn(elt), acc)};

Expand through `s:foldr`, and we get

    define s:map stream fn ->
      stream .s:case {
      	.s:empty -> s:empty;
	.s:next(head, tail) -> s:cons(fn(head), s:map tail fn);
      };

Delay:

    define nothing = { .case v -> v .nothing };
    define just x  = { .case v -> v .just x };

    define delay v ->
      -- Carefully written to avoid holding onto v for too long.
      -- Needs let rec cell = etc. to avoid the initial cell.set!
      let cell = ref ();
      do cell.set { let forced = v ();
      	       	    do cell.set { forced };
		    forced };
      { msg -> cell.get () msg };

Lazy map:

    define s:lazymap stream fn ->
      delay {stream .s:case {
      	.s:empty -> s:empty;
	.s:next(head, tail) = s:cons(delay {fn(head)}, delay {s:map tail fn});
      }};