Macros 宏调用函数在解释器中工作,在编译器中失败(SBCL+;CMUCL)

Macros 宏调用函数在解释器中工作,在编译器中失败(SBCL+;CMUCL),macros,lisp,common-lisp,Macros,Lisp,Common Lisp,如中所述,我通过调用函数编写了一个名为“fast”的宏: 这在SBCL和CMUCL下的REPL中起作用: $ sbcl This is SBCL 1.0.52, an implementation of ANSI Common Lisp. ... * (load "bug.cl") 22 22 $ 然而,不幸的是,代码不再编译: $ sbcl This is SBCL 1.0.52, an implementation of ANSI Common Lisp. ... * (compile-

如中所述,我通过调用函数编写了一个名为“fast”的宏:

这在SBCL和CMUCL下的REPL中起作用:

$ sbcl
This is SBCL 1.0.52, an implementation of ANSI Common Lisp.
...
* (load "bug.cl")
22
22

$
然而,不幸的是,代码不再编译:

$ sbcl
This is SBCL 1.0.52, an implementation of ANSI Common Lisp.
...
* (compile-file "bug.cl")
...
;   during macroexpansion of (FAST (+ 1 2 ...)). Use *BREAK-ON-SIGNALS* to
;   intercept:
;
;    The function COMMON-LISP-USER::CLONE is undefined.
因此,似乎通过在编译时使用宏“fast”调用函数(“clone”、“operation-p”),我在Lisp编译器中触发了问题(在CMUCL和SBCL中都进行了验证)


关于我做错了什么和/或如何修复这个问题,有什么想法吗?

没关系,我想出来了:我必须将宏调用的函数(因此在编译过程中是必需的)移动到一个单独的文件中,“先编译文件”它,“加载”它,然后“编译文件”带有宏的函数。

宏扩展绑定(通常)在编译时


这意味着在编译过程中遇到宏时,必须定义宏扩展过程中使用的任何函数(注意,宏扩展中不一定使用返回值)

  • 一个对象的多项相等性测试可由
    成员

  • 带逗号的反引号不起任何作用。你可以把它去掉

  • 通过a)将函数移动到其他文件并在使用宏之前编译/加载,b)使用
    EVAL-WHEN
    通知编译器评估函数的定义,或c)将函数作为本地函数添加到宏中,可以确保函数可用于宏

例如:

(defmacro fast (&rest sexpr)
  (labels ((operation-p (x)
             (member x '(+ - * /)))
           (clone (sexpr)
             (if (consp sexpr)
                 (destructuring-bind (head . tail) sexpr
                   (if (operation-p head)
                       `(the fixnum (,head ,@(clone tail)))
                     (cons (clone head) (clone tail))))
               sexpr)))
    (car (clone sexpr))))

请注意,这和您的
FAST
版本都不是完整的代码漫游器。它们只识别简单的函数调用(而不识别其他Lisp构造,如LAMBDA、LET、FLET、LABELS等)。

可能将答案放入答案中,然后接受它?仅使用函数编译文件是不够的。您还需要加载它。事实上,您是对的-我显然这样做了,但忘了写下来。我是LISP新手,您的代码显示了许多我不知道的事情-谢谢。
(defmacro fast (&rest sexpr)
  (labels ((operation-p (x)
             (member x '(+ - * /)))
           (clone (sexpr)
             (if (consp sexpr)
                 (destructuring-bind (head . tail) sexpr
                   (if (operation-p head)
                       `(the fixnum (,head ,@(clone tail)))
                     (cons (clone head) (clone tail))))
               sexpr)))
    (car (clone sexpr))))