Skip to content

Instantly share code, notes, and snippets.

@kisom
Created July 19, 2012 01:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kisom/3140167 to your computer and use it in GitHub Desktop.
Save kisom/3140167 to your computer and use it in GitHub Desktop.
Undefined symbol errors in Lisp

The other day, I got a strange error while writing a macro (actually, deftest from Peter Seibel's Practical Common Lisp. My defmacro looked like this:

(defmacro deftest (name parameters &body body)
  `(defun ,name ,parameters
     (let ((*test-name* ,name))
       ,@body)))

At first glance, it looks fine. So, I defined a few tests with it (check is another macro for reporting test results):

(deftest test-+ ()
  (check
   (= (+ 1 2) 3)
   (= (+ 1 2 3) 6)
   (= (+ -1 -3) -4)))

Trying to evaluate this, I got an error:

CL-USER> (deftest test-fn () (format t "testing~%"))
; in: DEFTEST TEST-+
;     (LET ((*TEST-NAME* TEST-+))
;       (FORMAT T "ohai~%"))
; 
; caught WARNING:
;   undefined variable: TEST-FN
; 
; compilation unit finished
;   Undefined variable:
;     TEST-FN
;   caught 1 WARNING condition
TEST-FN
CL-USER> 

I racked my brain trying to figure it out. Here's the macroexpand-1 of that definition:

(DEFUN TEST-FN ()
  (LET ((*TEST-NAME* TEST-FN))
    (FORMAT T "testing~%")))
T

Still being new to Lisp, I didn't see what was wrong with it. However, the LET gives it away:

  (LET ((*TEST-NAME* TEST-FN))

It tries to evaluate the symbol TEST-FN, which we haven't defined yet (we're still building the function; as Paul Graham writes in On Lisp, "building a function and associating it with a certain name are two separate operations." (page 13). Let's take a look back at the original defmacro: you'll notice that we're evaluating name in the LET:

     (let ((*test-name* ,name))

What I really wanted to do was to quote the value of name:

     (let ((*test-name* ',name))

With that, the testing suite works.

This is one reason I'm hand typing all the examples. It's bugs like this one that give me the best education and help me recognise when things go sideways later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment