[comp.lang.lisp] Answer to the Macro question

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (12/09/88)

In article <698@crin.crin.fr>, stephan@crin (Stephan BRUNESSAUX) writes:
>Is there anybody out there who can explain me what is wrong with this example
>which correctly runs in both interpreted and compiled mode on Symbolics 3620
>(Genera 7.2) and correctly ONLY in interpreted mode on TI Explorer II and on
>VAX running KCL (June 3, 1987) but not in compiled mode !?...
...
>Here come the problems. 
>Now, we generate a hash-table
>instead of a list.
>   |   >(defmacro test (a b)  
>   |      (let ((table (make-hash-table :size 1)))
>   |        (setf (gethash a table) b)
>   |        `(defun aux () 
>   |           (maphash #'(lambda (key val) 
>   |                        (format t "key: ~a - val: ~a~%" key val)) 
>   |                    ',table))))
>   |   TEST
 [ A transcript showing it working interpreted but not compiled ]

I think that your problem is that you're creating the hash table at macro
expansion time instead of at execution time.  Obviously this will (almost
definitely) work in interpreted mode, because the two environments are the
same.  However, when compiling a file, the compiler is expected to create
the object at COMPILE time, save it into the file (perhaps including any 
other information that's associated with it), and load it correctly when 
loading the file.  I'm just impressed that Symbolics was able to handle it.

As a fix, I suggest that you change the above macro to:

   |    (defmacro test (a b)  
   |      `(let ((table (make-hash-table :size 1)))
   |         (setf (gethash ,a table) ,b)
   |         (defun aux () 
   |           (maphash #'(lambda (key val) 
   |                        (format t "key: ~a - val: ~a~%" key val)) 
   |                    ',table))))

For interpreted code this will make no difference.  For compiled code it will
cause the hash table to be generated at load time, and thus the references
to the table from within the compiled code will be correct.


Bruce Krulwich