Max
Max

Reputation: 101

clisp: variable x has no value

I'm receiving the error variable MAP has no value in my Common Lisp code (I am using the clisp shell in the Ubuntu terminal). My code looks like this (*map* is just an association list, so you can skip over it):

(setf *map* '((shore (stars cast reflections on the rippling sea.  
                            it fills you with a strong but unplaceable emotion.) 
                     (east forest))
              (forest (a roof of treetops blots out the sun.  something rustles 
                         behind you.) 
                      (west shore) 
                      (north cliff))
              (cliff (you nearly stumble into a long and fatal fall into the 
                          sea far below you.  you feel a strange urge to throw 
                          yourself off the ledge.  it would probably wisest to 
                          leave this place.) 
                     (south forest))))

(defun walk-direction (direction room map)
  (second (assoc direction (cddr (assoc room map)))))

(defmacro defspel (&rest rest) `(defmacro ,@rest))

(defspel walk-to (direction room map)
  `(walk-direction ',direction ',room map))

(walk-to east shore *map*)

(I'm following the liserpati tutorial, for those wondering about any oddities I might be committing)

If change walk-to to

(defspel walk-to (direction room)
  `(walk-direction ',direction ',room *map*))

then everything goes perfectly well. However, this breaks the beautiful convention of functional programming which I would like to keep as intact as possible-- not to mention the fact that I still have no idea why my code doesn't work.

Upvotes: 1

Views: 3746

Answers (2)

Kaz
Kaz

Reputation: 58500

Let's take a look at:

(defspel walk-to (direction room map)
  `(walk-direction ',direction ',room map))

Here, the symbol map is inside a backquote, and it isn't unquoted. This means that it is just a literal datum. It has no connection to the map argument of the walk-to spell.

The generated walk-direction code evaluates in an environment in which the map argument is no longer visible; it is treated as a free variable reference which expects a global variable to exist.

When you change map to *map* you fix part of the problem; the generated code then refers to the dynamic variable *map* in the global environment.

But this is still broken, because walk-to is supposed to generate code which uses the map which is passed in, which is not necessarily the global map (or else why have a parameter).

You probably want this:

(defspel walk-to (direction room map)
  `(walk-direction ',direction ',room ,map))

So that, for instance, the call (walk-to north shore *map*) will generate the code (walk-direction 'north 'shore *map*). The walk-to macro quotes the direction and room symbols for you, but should not quote *map*, since that is Lisp variable which we need to evaluate to the map object it represents, and not a game symbol like north.

Upvotes: 0

m-n
m-n

Reputation: 1446

The definition of walk-to is missing a comma before map. Take a look at the output of:

(macroexpand-1 '(walk-to east shore *map*))

Upvotes: 5

Related Questions