正如标题所说,我如何(以编程方式)以可移植的方式(如果可能)检查一个符号是否代表一个符号宏?
CL-USER> (define-symbol-macro some-macro some)
SOME-MACRO
CL-USER> (macro-function 'some-macro)
NIL
CL-USER> (fboundp 'some-macro)
NIL
SBCL 有 sb-impl::info:
CL-USER> (describe 'sb-impl::info)
SB-INT:INFO
[symbol]
INFO names a compiled function:
Lambda-list: (CATEGORY KIND NAME)
Declared type: (FUNCTION (T T T) (VALUES T T &OPTIONAL))
Source file: SYS:SRC;COMPILER;GLOBALDB.LISP
INFO has a compiler-macro:
Source file: SYS:SRC;COMPILER;EARLY-GLOBALDB.LISP
(SETF INFO) names a compiled function:
Lambda-list: (NEW-VALUE CATEGORY KIND NAME)
Declared type: (FUNCTION (T T T T) (VALUES T &OPTIONAL))
Source file: SYS:SRC;COMPILER;GLOBALDB.LISP
(SETF INFO) has a compiler-macro:
Source file: SYS:SRC;COMPILER;EARLY-GLOBALDB.LISP
似乎有效:
CL-USER> (sb-impl::info :variable :kind 'some-macro)
:MACRO
T
这就是他们在“描述”函数的源代码中所使用的内容(我通过查看那里发现了这一点)。
在此之前,我一直在研究 clhs,但一无所获。是我错过了还是没有标准方法?是否有一些可移植/“简单”的库可以做到这一点?
编辑:
在得到有用的答案之后,我找到了cltl2 的“简单”包装器。它似乎也在 quicklisp 中,因此除了内置的 'special-operator-p'之外,我们还可以拥有:
(defun special-variable-p (symbol)
(multiple-value-bind (info ignore1 ignore2)
(variable-information symbol)
(declare (ignore ignore1 ignore2))
(eq :special info)))
(defun symbol-macro-p (symbol)
(multiple-value-bind (info ignore1 ignore2)
(variable-information symbol)
(declare (ignore ignore1 ignore2))
(eq :symbol-macro info)))
我实际上更喜欢广义布尔值,看起来更有用,所以我使用这个:
(defun symbol-macro-p (symbol)
"Return if SYMBOL stands for a symbol macro."
(multiple-value-bind (info ignore1 ignore2)
(variable-information symbol)
(declare (ignore ignore1 ignore2))
(when (eq :symbol-macro info)
(multiple-value-bind (expansion ignored)
(macroexpand symbol)
(declare (ignore ignored))
expansion))))
CL-USER> (symbol-macro-p 'some-macro)
SOME
CLtL2 中有一个函数
VARIABLE-INFORMATION
¹,但不是 Common Lisp 标准,至少一些 CL 实现支持该函数,该函数可用于判断某个符号是否具有符号宏。在 SBCL 中,可通过以下方式访问:
Clozure 在包中有它
CCL
:Allegro 在其文档中列出了它,但我没有副本可以测试。
HCL
LispWorks根据其文档将其包含在包中,但我没有它的副本。正如@myname 发现的那样,它在
trivial-cltl2
包中可用,因此您不必自己弄清楚该函数位于哪个包中,从而更容易在多个实现中使用。1:在Rainer 的回答中,我发现了这个函数,它是关于另一个问题的,关于当我在寻找重复项时如何判断一个变量是否是特殊的。