Common lisp 用宏生成动态函数

Common lisp 用宏生成动态函数,common-lisp,Common Lisp,我正在组合一个宏来生成该样式的简单函数: (defun hello () (format t "hello~&")) 每个新功能都将被替换 (defmacro generate-echoers (list) `(let ((list-of-functions (loop for var in ,list collect `(defun ,(intern var) () (fo

我正在组合一个宏来生成该样式的简单函数:

(defun hello ()
  (format t "hello~&"))
每个新功能都将被替换

(defmacro generate-echoers (list)
  `(let ((list-of-functions
         (loop for var in ,list
            collect
              `(defun ,(intern var) ()
                 (format t ,(concatenate var "~&"))))))
  `(progn
     ,list-of-functions)))
我开发了上面的函数,它最终证明我还没有掌握报价时间和扩展阶段

预期用途如下:
(生成回音“(“hi”“ping”“pong”)=>;一个函数列表,每个函数都会说出它们的名字,就像上面的HELLO一样。

您的代码可以简化,并变得更正确,如下所示:

(defmacro generate-echoers (list)
  `(progn ,@(loop :for var :in list
               :collect `(defun ,(intern (format nil "~:@(~A~)" var)) ()
                           (format t ,(concatenate 'string var "~&"))))))
首先,您必须将
循环的结果拼接到生成的主体中


您还忘记了,
concatenate
接受类型参数并对所有变量进行升格(否则您将获得函数名,如
|foo |
)。

如果将符号传递给generate Echors宏(而不是字符串),则不再需要intern调用:

(defmacro generate-echoers (&rest echoers)
  `(progn
     ,@(mapcar (lambda (var)
                 `(defun ,var () 
                    (format t ,(format nil "~(~a~)~&" var))))
               echoers)))

要生成的函数:

(defun hello ()
  (format t "hello~&"))
我首先编写一个函数,创建上述代码:

(defun make-echoers (name)
  `(defun ,(intern (string-upcase name)) ()
     (format t ,(concatenate 'string name "~&"))))
请注意,在公共Lisp中,符号默认为大写-因此我们也使用大写

然后您可以测试它:

CL-USER 1 > (make-echoers "hello")
(DEFUN HELLO NIL (FORMAT T "hello~&"))
工作。现在让我们使用它:

(defmacro generate-echoers (list)
  `(progn ,@(mapcar #'make-echoers list)))
测试它:

CL-USER 2 > (macroexpand-1 '(generate-echoers ("hi" "ping" "pong")))
(PROGN
  (DEFUN HI NIL (FORMAT T "hi~&"))
  (DEFUN PING NIL (FORMAT T "ping~&"))
  (DEFUN PONG NIL (FORMAT T "pong~&")))

`(progn@(loop
为我解决了它。剩下的我自己整理好了。非常感谢!函数的名称需要是SYMBOL或一个根据Hyperspec的列表。我不理解列表部分,我认为它必须是可设置的。我传递了一个字符串列表。我打赌你传递了一个符号列表?而且,我喜欢mapcar。比loop h干净得多有趣的是,我没有想到使用defun来生成defun。问题已经解决了,但是+1!为thread necro表示歉意;是否可以更改它,以便传递一个值为list
的符号(“hi”“ping”“pong”)
,而不是直接传递列表?我尝试使用
,list
,但失败。@詹姆斯·波特:您需要确保检索到符号值。例如,更改宏以检查符号并尝试检索符号值。打开另一罐蠕虫。。。