Enums 公共Lisp等价于C枚举

Enums 公共Lisp等价于C枚举,enums,lisp,common-lisp,Enums,Lisp,Common Lisp,最近我在尝试学习一些Lisp(Common Lisp),我想知道是否有一种方法可以像在C中通过枚举一样给常量命名 我不需要枚举的完整特性集。最后,我只想要快速可读的代码 我尝试过全局函数和小函数,但这总是伴随着性能的下降。将数字插入代码总是更快。枚举对于Lisp来说是多余的,原因是所有符号都是它们自己的标识,因此您可以使用它们,例如: [dsm@localhost:~]$ clisp -q [1]> (setf x 'some) ;' SOME [2]> (eq x 'some) ;

最近我在尝试学习一些Lisp(Common Lisp),我想知道是否有一种方法可以像在C中通过枚举一样给常量命名

我不需要枚举的完整特性集。最后,我只想要快速可读的代码


我尝试过全局函数和小函数,但这总是伴随着性能的下降。将数字插入代码总是更快。

枚举对于Lisp来说是多余的,原因是所有符号都是它们自己的标识,因此您可以使用它们,例如:

[dsm@localhost:~]$ clisp -q
[1]> (setf x 'some) ;'
SOME
[2]> (eq x 'some) ;'
T
[3]>

在Lisp中执行枚举的正常方法是使用符号。符号被截取(替换为指向符号表中其条目的指针),因此它们与整数一样快,与其他语言中的枚举常量一样可读

那么,您可以在C中的何处编写:

enum { apple, orange, banana, };
然后您可以使用
declare
typep
typecase
等中的类型
fruit
,您可以编写专门针对该类型的通用函数。

例如,您想要命名字体大小:

(defconstant +large+ 3)
(defconstant +medium+ 2)
(defconstant +small+ 1)
你可以写一个宏来缩短它

上述常量定义通常仅在需要将这些数字传递给某些外部非Lisp代码时编写

否则,只需使用关键字符号::大、:中和:小

你可以用EQ测试它们,以及任何使用平等测试的东西

(let ((size :medium))
  (ecase size
    (:small ...)
    (:medium ...)
    (:large ...)))
您还可以为其编写方法:

(defmethod draw-string (message x y (size (eql :large))) ...)
如前所述,您可以定义一个集合类型:

(deftype size () '(member :small :medium :large))
然后,您可以检查是否存在以下情况之一:

(let ((my-size :medium))
  (check-type my-size size))
如果我的尺码不是:小、:中或:大中的一个,则上面显示的是一个错误

您还可以在defclass表单中使用该类型:

(defclass vehicle ()
   ((width :type size :initarg :width)))
现在,您可以创建如下对象:

(make-instance 'vehicle :width :large)
当您将插槽设置为非法值时,一些常见的Lisp实现将进行检查

如果现在创建vehicle类的对象,则插槽将为:大、:中或:小。如果在调试器、检查器或其他工具中查看对象,您将看到符号名称,而不是1、2或3(或通常使用的任何值)


这是Lisp风格的一部分:尽可能使用符号名。只在外部函数的接口代码中使用带有数字值的符号(如调用使用枚举的外部C代码)。

是的,但最好使用关键字。这是一个好的观点:通过使用关键字,您不必担心符号在哪个包中。实际上,泛型函数只能专门用于类,不是任意类型。但是您可以为符号编写方法。(defmethod draw line(xy(style(eql:虚线)))…)如果您想要稍微强一点的输入,该怎么办?我想确保我没有出现直到运行时才会被检测到的打字错误?我不是一个真正的lisp人,我知道它不是一种强类型语言,只是好奇而已。如果你想保留更大的数组,比如在游戏或模拟的世界模型中,数值常量(相对于关键字)可能也很有用。那么,你的“占用地图”就可以紧凑而有效地追踪各种各样的东西,比如墙壁、怪物和宝藏。常数间隔可用于对实体进行分类,如
(defun monster-p(x)(和(>=x+最小怪物数+)(考虑到上面的
defconstant
调用,再加上后面使用关键字的示例,我突然想到,在传递到非lisp代码时,可能会将这两个函数混合使用:
(defun size number(the size)(选中键入size size)(case(:small+small+):medium+medium+(:large+large+)))
。或者可以跳过
检查类型
,使用
ecase
而不是
case
。也可以类似地编写与大小成反比的
数字。
(make-instance 'vehicle :width :large)