我想学习一些Lisp语言(Common Lisp的)最近,我不知道是否有给定的数字,就像你可以在C通过枚举做一个名字的一种方法.
我不需要枚举的完整功能集.最后我只想有快速和可读的代码.
我已经尝试了全局和小函数,但总是伴随着性能的降低.只需将数字插入代码总是更快.
在Lisp中执行枚举的常规方法是使用符号.符号得到实现(用符号表中的条目指针替换),因此它们与整数一样快,并且与其他语言中的枚举常量一样可读.
所以在C中你可以写:
enum { apple, orange, banana, };
在Lisp中你可以使用'apple
,'orange
而'banana
直接.
如果需要枚举类型,则可以使用以下内容定义deftype
:
(deftype fruit () '(member apple orange banana))
然后你可以使用类型fruit
中declare
,typep
,typecase
等等,并且您可以编写专门针对该类型的泛型函数.
例如,您想要命名字体大小:
(defconstant +large+ 3) (defconstant +medium+ 2) (defconstant +small+ 1)
你可以编写一个宏来缩短它.
上面的常量定义通常只有在需要将这些数字传递给某些外部非Lisp代码时才会写入.
否则,人们只会使用关键字符号:: large,:medium和:small.
您可以使用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))
如果my-size不是以下之一,则上面会发出错误信号:small,:medium或:large.
您还可以使用defclass形式的类型:
(defclass vehicle () ((width :type size :initarg :width)))
现在你要创建像这样的对象:
(make-instance 'vehicle :width :large)
一些Common Lisp实现将检查何时将插槽设置为某个非法值.
如果您现在创建类车辆的对象,则插槽将是以下之一:large,:medium或:small.如果在调试器,检查器或其他工具中查看对象,您将看到符号名称而不是1,2或3(或者您通常使用的任何值).
这是Lisp风格的一部分:尽可能使用符号名称.仅在外部函数的接口代码中使用带数值的符号(例如调用使用枚举的外部C代码).
枚举对于Lisp是多余的,原因是所有符号都是它们自己的标识,所以你可以使用它们,例如:
[dsm@localhost:~]$ clisp -q [1]> (setf x 'some) ;' SOME [2]> (eq x 'some) ;' T [3]>