HYPERTHINGS

Lazy Let


Or, the Continuing Joy of Symbol Macros

A possibly harebrained use of symbol macros to produce variables that evaluate "lazily". A short one.

Check It Out

This is your REPL

    ;; Boring Binding  
     > (let* ((one (progn (print "binding one") 10))  
             (two (progn (print "biding two") (* one one)))  
             (three (progn (print "binding three") 1000)))  
         (if (zerop (random 2))  
             three  
             two))  
      
     "binding one"  
     "biding two"  
     "binding three"  
     1000 

This is your REPL on lazy:

     ;; Living Lazily  
      > (lazy ((two (progn (print "forcing two") (* one one)))  
               (one (progn (print "forcing one") 10))  
               (three (progn (print "forcing three") 1000)))  
          (if (zerop (random 2))  
               three  
               two))  
      
     "forcing two"  
     "forcing one"  
     100 

Any questions?

A Macro

Today's hidden hero is humble symbol-macrolet:

     ;; Folks, tell me all the ways this will fall on its lazy face.  
     (defmacro lazy ((&rest binding-forms) &body body)  
       (let ((lazy-control  
               (loop :for (name form) :in binding-forms  
                     :collect (list name form (gensym "CACHED") (gensym "FORCED")))))  
         `(let ,(loop :for (n frm c f) :in lazy-control  
                      :collect `(,c nil)  
                      :collect `(,f nil))  
            (declare (ignorable ,@(loop for (nm fm c f) :in lazy-control  
                                        :collect c :collect f)))  
            (symbol-macrolet  
                ,(loop :for (name form cached forced) :in lazy-control  
                       :collect `(,name (if ,forced ,cached  
                                            (setf  
                                             ,forced t  
                                             ,cached ,form))))  
              ,@body))))  
     

That's all for today. Hope you enjoyed another half-baked Parenthetical Curio!