Common Lisp相当于C枚举

Nil*_*nck 18 lisp enums common-lisp

我想学习一些Lisp语言(Common Lisp的)最近,我不知道是否有给定的数字,就像你可以在C通过枚举做一个名字的一种方法.

我不需要枚举的完整功能集.最后我只想有快速可读的代码.

我已经尝试了全局和小函数,但总是伴随着性能的降低.只需将数字插入代码总是更快.

Gar*_*ees 21

在Lisp中执行枚举的常规方法是使用符号.符号得到实现(用符号表中的条目指针替换),因此它们与整数一样快,并且与其他语言中的枚举常量一样可读.

所以在C中你可以写:

enum {
   apple,
   orange,
   banana,
};

在Lisp中你可以使用'apple,'orange'banana直接.

如果需要枚举类型,则可以使用以下内容定义deftype:

(deftype fruit () '(member apple orange banana))

然后你可以使用类型fruitdeclare,typep,typecase等等,并且您可以编写专门针对该类型的泛型函数.

  • 是的,但更好地使用关键字. (6认同)
  • 但是你可以为符号编写方法.(defmethod draw-line(xy(style(eql:dashed)))...) (5认同)

Rai*_*wig 15

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

(defconstant +large+ 3)
(defconstant +medium+ 2)
(defconstant +small+ 1)
Run Code Online (Sandbox Code Playgroud)

你可以编写一个宏来缩短它.

上面的常量定义通常只有在需要将这些数字传递给某些外部非Lisp代码时才会写入.

否则,人们只会使用关键字符号:: large,:medium和:small.

您可以使用EQ和使用某些测试进行相等性测试的所有内容来测试它们.

(let ((size :medium))
  (ecase size
    (:small ...)
    (:medium ...)
    (:large ...)))
Run Code Online (Sandbox Code Playgroud)

你也可以为它编写方法:

(defmethod draw-string (message x y (size (eql :large))) ...)
Run Code Online (Sandbox Code Playgroud)

如上所述,您可以定义集类型:

(deftype size () '(member :small :medium :large))
Run Code Online (Sandbox Code Playgroud)

然后你可以检查是否有其中任何一个:

(let ((my-size :medium))
  (check-type my-size size))
Run Code Online (Sandbox Code Playgroud)

如果my-size不是以下之一,则上面会发出错误信号:small,:medium或:large.

您还可以使用defclass形式的类型:

(defclass vehicle ()
   ((width :type size :initarg :width)))
Run Code Online (Sandbox Code Playgroud)

现在你要创建像这样的对象:

(make-instance 'vehicle :width :large)
Run Code Online (Sandbox Code Playgroud)

一些Common Lisp实现将检查何时将插槽设置​​为某个非法值.

如果您现在创建类车辆的对象,则插槽将是以下之一:large,:medium或:small.如果在调试器,检查器或其他工具中查看对象,您将看到符号名称而不是1,2或3(或者您通常使用的任何值).

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


dsm*_*dsm 6

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

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