I've been thinking on the problem a bit and found another way to tackle
it, using this incredibly *UGLY* function (all of them formatted as
the output of 'pp, I have no idea how to make it more aesthetically
pleasing):

(de lazy Prg
   (let L (box (cons))
      (con
         (val L)
         (list
            (list
               'cdar
               (list
                  'con
                  L
                  (list
                     'list
                     (list 'cons ''quote (cons 'prog Prg)) ) ) ) ) )
      (val L) ) )
-> lazy
: (setq A (lazy (prinl "Computing...") 42))
-> (NIL (cdar (con $384526428 (list (cons 'quote (prog (prinl
"Computing...") 42)))))) 
: (A)
Computing...
-> 42
: (A)
-> 42
: A
-> (NIL '42)

As you can see, the resulting lambda modifies itself to become just the
quoted result on the first call. 

The way 'lazy works is by first boxing a cons pair to form the head of
the lambda expression. Then it concatenates a function body to that
head that is itself a call to 'con to replace itself with the computed
result in a quote. 

The box symbol is not necessary at all, I included it to make the
resulting expression printable. This version works the same, but
crashes print (rather, puts it in an infinite loop) if you use it in
the repl without a 'nil guard.

(de lazy Prg
   (let L (cons)
      (con
         L
         (list
            (list
               'cdar
               (list
                  'con
                  (cons 'quote L)
                  (list
                     'list
                     (list 'cons ''quote (cons 'prog Prg)) ) ) ) ) )
      L ) )
-> lazy
: (nil (setq A (lazy (prinl "Computing...") 42)))
-> NIL
: (A)
Computing...
-> 42
: (A)
-> 42
: A
-> (NIL '42)

Cheers,
José
--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to