正如标题所说,我如何(以编程方式)以可移植的方式(如果可能)检查一个符号是否代表一个符号宏?
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