我正在“符号计算的温和介绍”中练习练习14.11,并编写了以下函数:
(defmacro compile-machine (nodes)
`(progn ,@(mapcar #'compile-node nodes)))
在调用(compile-machine *nodes*)
时,*nodes*
是NODE
结构的列表,我收到以下错误:
Error: *NODES* is not of type LIST.
所以我看到*nodes*
是和
CL-USER 116 > *nodes*
(#<Node START> #<Node HAVE-5> #<Node HAVE-10> #<Node HAVE-15> #<Node HAVE-20> #<Node HAVE-25> #<Node END>)
CL-USER 117 > (type-of *nodes*)
CONS
CL-USER 118 > (listp *nodes*)
T
似乎*nodes*
确实是一个列表。我在这里做错了什么?
编辑:更多可能澄清的代码
(defun compile-arc (arc)
`((equal this-input ',(arc-label arc))
(format t "~&~A" ,(arc-action arc))
(,(node-name (arc-to arc)) (rest input-syms))))
(defun compile-node (node)
`(defun ,(node-name node) (input-syms &aux (this-input (first input-syms)))
(cond ((null input-syms) ',(node-name node))
,@(mapcar #'compile-arc (node-outputs node)) ;isn't this basically the same?
(t (error "No arc from ~A with label ~A." ;and yet Lisp doesn't complain
',(node-name node) this-input)))))
答案 0 :(得分:3)
您不是在编写函数而是编写宏。
宏在代码上运行。您的代码(compile-machine *nodes*)
将宏扩展转换为其他代码,然后执行。宏的参数是未评估的符号*nodes*
。你不能mapcar
一个符号。
在我看来,你确实想写一个函数。请使用defun
:
(defun compile-machine (nodes)
(mapcar #'compile-node nodes))
答案 1 :(得分:2)
节点不是列表,它是一个符号。宏的“神奇之处”在于你,宏编写者,你可以评估这些论者 - 而不是Lisp读者。
所以,你传递节点,这是一个符号。你需要尊重它才能获得它的价值。
也许就像这样(告诫我这里真的生锈了,这可能是错的,但基本前提是关闭的)
(defmacro compile-machine (nodes)
`(progn ,@(mapcar #'compile-node ,nodes)))
答案 2 :(得分:2)
*NODES*
的值是一个列表,但它本身就是一个符号。