(defmacro test (&key list &environment env)
(typecase (get-type list env)
(list `(do-something (list ,@list)))
(integer `(do-something (list ,list ,list ,list)))))
(test :list '(1 2 3)) ; => (do-something (list 1 2 3))
(test :list (* 1 2)) ; => (do-something (list (* 1 2) (* 1 2) (* 1 2)))
是否可以在宏扩展时获取list
的类型? (我称之为get-type
)
它不适用于评估,因为此时变量可能不存在,并且可能会更改其他一些值,这些值不应该更改。
或者我应该让我的宏扩展成为一个也调用 typecase 的表单?
最佳答案
大多数 Lisp 方言都可以被视为动态类型。 Common Lisp 也不异常(exception)。添加了类型和类型声明,以允许在运行时处理类型:用于运行时类型检查和运行时类型分派(dispatch)。它还允许 Common Lisp 实现在编译时使用类型信息来生成更快的代码。使用类型信息进行编译时类型检查或在宏的用户级别不是我们的目标。尽管在早期,至少 CMUCL(以及后来的 SBCL 和 Scieneer CL)使用类型声明和类型推断来进行一定量的编译时类型检查。大多数其他实现不进行编译时类型检查,而少数实现进行类型推断。
请注意,您可以在运行时添加或重新定义类型。类型层次结构也可以在运行时更改(例如类层次结构)。
如果你有一个实际的对象,人们可以确定 Lisp 系统在编译时认为它是什么类型。
但是函数返回值的类型是什么?该信息可以来自类型声明或类型推断。后者在 Common Lisp 中不可移植 - 可能存在特定于实现的方法来从类型推断中获取信息或使用库中的类型推断器。
有关函数类型声明的信息,Common Lisp 的某些实现提供了函数 FUNCTION-INFORMATION
(最初为 ANSI CL 提出,但并未将其纳入实际标准)。
在 LispWorks 6.1 中:
CL-USER 42 > (compile (defun foo () (the fixnum 3)))
FOO
NIL
NIL
CL-USER 43 > (declaim (ftype (function () fixnum) foo))
T
CL-USER 44 > (function-information 'foo)
:FUNCTION
NIL
((FTYPE FUNCTION NIL FIXNUM))
另请参阅变量信息
。 FUNCTION-INFORMATION
和 VARIABLE-INFORMATION
也记录在 CLtL2 中,但没有记录在 Common Lisp Hyperspec 中(因为它们不在标准中)。
通常在宏扩展时使用此类类型信息会引发一整套蠕虫病毒。对于基本使用,我建议考虑运行时类型并创建运行时类型分派(dispatch)的代码 - 除非您在编译时确实需要类型信息。
关于types - 获取宏中的类型信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29429799/