我在Common Lisp代码中收到错误variable MAP has no value
(我在Ubuntu终端中使用了clisp shell)。我的代码看起来像这样(*map*
只是一个关联列表,所以你可以跳过它):
(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*)
(我正在关注liserpati教程,对于那些对我可能犯下的任何奇怪事情感到疑惑的人)
如果改变步行到
(defspel walk-to (direction room)
`(walk-direction ',direction ',room *map*))
然后一切都很顺利。然而,这打破了函数式编程的美妙惯例,我希望尽可能保持完整 - 更不用说我仍然不知道为什么我的代码不起作用。
答案 0 :(得分:6)
walk-to
的定义在map
之前缺少逗号。看看输出:
(macroexpand-1 '(walk-to east shore *map*))
答案 1 :(得分:0)
我们来看看:
(defspel walk-to (direction room map)
`(walk-direction ',direction ',room map))
这里,符号映射在反引号内,并且不是不引用的。这意味着它只是一个文字数据。它与map
法术的walk-to
参数无关。
生成的walk-direction
代码在map
参数不再可见的环境中进行评估;它被视为一个自由变量引用,它需要一个全局变量。
当您将map
更改为*map*
时,您可以解决部分问题;然后,生成的代码引用全局环境中的动态变量*map*
。
但是这仍然被打破,因为walk-to
应该生成使用传入的map
的代码,这不一定是全局地图(或者为什么有参数)。 / p>
你可能想要这个:
(defspel walk-to (direction room map)
`(walk-direction ',direction ',room ,map))
因此,例如,调用(walk-to north shore *map*)
将生成代码(walk-direction 'north 'shore *map*)
。 walk-to
宏为你引用方向和房间符号,但不应引用*map*
,因为那是我们需要评估它所代表的地图对象的Lisp变量,而不是{{1}这样的游戏符号{1}}。