我研究了define-easy-handler macro from the hunchentoot package(它创建了一个名为NAME的函数),并使defun部分工作,但是我无法通过这个宏将NAME推送到名为{{1}的列表中}:
*observers*
对(defmacro add-observer (name params &body body)
;; add NAME to the list *observers*
`(push ,name *observers*)
;; define a lisp function with the name NAME
;; with key arguments given in PARAMS
`(defun ,name (&key ,@(loop for p in params
collect p))
,@body)))
的示例调用是:
#'add-observer
NAME功能已定义且工作正常,但NAME未添加到列表(add-observer below-80 (id blood-sugar)
(when (< blood-sugar 80)
(format t "Patient No: ~A is hypoglycemic." id))
中。如果我将两个s表达式都放在预测中并不重要。 macroexpand清楚地显示没有预测的*observers*
调用的缺失。我在解释什么错误?
当我尝试这样的预测时:
push
它以`(progn
(push ...
(defn ...
失败。当我把反引号放回#&#39; push和#&#39; defun时,再次推送#&#39; push不起作用。
答案 0 :(得分:3)
宏获取源表单并计算第一个结果表单:(push foo *observers*)
然后将此表单返回到垃圾收集器的必杀技,因为它没有存储在任何地方,没有返回给任何调用者,没有执行,......立刻就是垃圾。所以一个聪明的编译器甚至可以删除它......
宏表单然后计算第二个表单(defun ...)
。此表单从宏返回,然后执行。
要么在宏扩展时执行第一个表单,那么你需要通过删除反引号和逗号来使其可执行。
或者您希望将其包含在生成的源代码中,然后您需要返回一个progn
表单,其中包含所有子表单。
当宏表单多次执行/展开时,您可能还想考虑PUSH
与PUSHNEW
的效果......
使用宏时不需要的符号评估
记住:符号是Lisp代码中的变量。如果你想将它们视为符号本身,那么你需要引用它们出现的符号或数据结构。
说,你的表格是:
(add-observer below-80 ...)
这意味着below-80
没有引用。
现在,您也可以生成符号未加引号的代码。
(push below-80 ...)
当然,这会尝试评估变量 below-80
,它似乎在您的代码中未绑定。
如果您希望在评估期间将below-80
视为符号,则必须引用它:'below-80
。生成的代码应如下所示:
(push 'below-80 ...)
在你的代码中引用它
(add-observer 'below-80 ...)
或通过宏进入扩展:
(push 'below-80 ...)
反引号模板是
`(progn
(push ',name ...)
...)