理解错误“是宏,不是函数”

问题描述 投票:0回答:1
我已经遇到过几次这样的错误了

is a macro, not a function

。但发现很难复制原因。

我后来发现我看到错误的原因是因为我在使用它的文件中定义了一个宏。我使用定义上面的宏。

例如:

在 sbcl 中,我创建了一个用于从终端进行交互式中断的函数。

(defun some-long-running-thread () ... #+sbcl (sb-sys:interactive-interrupt () (progn (color :red (princ "C-c was pressed")) ;; <-- my macro (uiop:quit)))) (defmacro color (color &body body) `(multiple-value-bind (col val) (cl-ansi-text:with-color (,color) (progn ,@body)) (declare (ignore col)) val))
幕后实际发生了什么,函数可以按任何顺序定义,但宏不能?

注意:我经常在使用宏的同一个文件中定义宏。

macros common-lisp sbcl file-compilation
1个回答
0
投票

宏在编译时进行源代码转换。

假设您想在源代码中使用宏

foo

假设您的代码首先使用

(foo 123)

。这里编译器不知道 
foo
 是什么。编译器假定它是一个函数。因此,它创建了对未知函数的函数调用的代码
foo

现在您可以用相同的名称定义一个宏

foo

。
这有效果:

  • 编译器之前假设

    foo

    是一个函数。现在您将其定义为宏 -> 因此出现警告。

  • 编译器已经使用

    foo

     运算符将代码编译为函数调用。 -> 它不会重新编译它。

引入宏时的规则

a) 在源代码中使用之前定义所有宏

b) 在源代码中使用宏之前提供宏使用的所有功能(函数、宏……)。

文件编译器在看到该文件中的用法时将需要宏定义:在编译时需要宏来宏扩展代码。

实用:在文件中编译函数与宏

在可能使用宏的函数之前先定义宏。

文件编译器 (->

compile-file

) 将函数和宏定义视为不同的:

  • 函数定义将被编译,但不会加载到

    编译时环境中。因此,在文件的文件编译期间,默认情况下,任何定义的函数在编译期间都将不可调用。

  • 宏定义将被编译

    并且它将被加载到编译时环境中。因此,正在编译的文件中定义的宏可以在该文件的编译过程中展开。

© www.soinside.com 2019 - 2024. All rights reserved.