假设我们有几个文本样式:bold、ìtalic、thin、regular。现在我们有了一个绘制一些文本的函数:
(defun draw-text-string (text style stream)
...)
整数枚举
我们将如何传递样式信息?我们可以将它们编码为数字:
(defconstant +regular+ 0)
(defconstant +thin+ 1)
(defconstant +bold+ 2)
(defconstant +italic+ 3)
我们可以将它们编码为位:
(defconstant +regular+ #b0001) ; 1
(defconstant +thin+ #b0010) ; 2
(defconstant +bold+ #b0100) ; 4
(defconstant +italic+ #b1000) ; 8
枚举类型通常将这些映射隐藏在类型声明后面。
当我们调用绘图函数时,我们以某种方式传递这些数字:
(draw-text-string "hello" +thin+ *standard-output*)
我们可以这样写:
(draw-text-string "hello" 1 *standard-output*)
如果我们有位编码,我们也可以传递一个集合:
(draw-text-string "hello" (logxor +thin+ +italic+) *standard-output*)
(draw-text-string "hello" 10 *standard-output*)
优点是编码非常紧凑。如果我们调试程序,在 Lisp 中我们会看到数字。在静态类型语言中,调试器可以访问类型信息并将值显示为名称。
这种枚举通常不会在 Lisp 中完成 - 仅当需要与外部例程接口时,通常遵循 C 约定。
枚举值作为符号
在 Lisp 中,也可以使用符号来实现这一目的。作为单个符号或作为符号列表。这里符号本身就是值,它们不用作变量。
(draw-text-string "hello" 'thin *standard-output*)
(draw-text-string "hello" '(thin italic) *standard-output*)
在 Common Lisp 中,我们经常使用自评估关键字符号。这样我们就不需要考虑包(命名空间)了。
(draw-text-string "hello" :thin *standard-output*)
(draw-text-string "hello" '(:thin :italic) *standard-output*)
两者的优点是我们传递命名对象(符号),在 Lisp 系统中调试期间更容易理解。缺点是我们现在可以传递符号列表,这比数字或位向量之类的效率略低。
运行时类型检查通常通过MEMBER 类型完成。