muu*_*gnu 20 c lisp struct common-lisp
在C类语言中,从一开始就在每本入门书中都强调结构/记录和对象.然后,他们的完整系统围绕管理这些结构,它们的相互关系和继承而设计.
在Lisp文档中,你通常可以找到1-2页关于Lisp"也"如何有一个defstruct,一个简单的例子,通常就是这样.而且,根本没有提到结构的嵌套.
对于来自C背景的人来说,首先看来,分层组织不同的数据类型不是Lisp中的首选方法,但除了CLOS之外,CLOS是一个完整的对象系统,如果你只是想要结构,那就太复杂了,除了疯狂一切在列表中,没有明显的方法来转移您的C结构知识.
什么是层次组织数据的惯用Lisp方法,最类似于C结构?
-
我认为我的问题的总结答案是:对于初学者学习目的,defstruct和/或plists,虽然"遗留特征",可以使用,因为它们最接近C结构,但它们已被更大的取代更多灵活的defclass/CLOS,这是大多数Lisp程序今天使用的.
这是我关于SO的第一个问题,所以感谢大家的回答.
Rai*_*wig 22
使用CLOS.这并不复杂.
否则使用结构.
如果您有特定的问题如何使用它们,那么请问.
(defclass point ()
((x :type number)
(y :type number)))
(defclass rectangle ()
((p1 :type point)
(p2 :type point)
(color :type color)))
Run Code Online (Sandbox Code Playgroud)
这样的东西最终会导致像CLIM中的矩形这样的接口(Common Lisp Interface Manager).
历史
稍微扩展一下:历史上,"结构"已被用于某些低级别的情况.结构具有单一继承,并且插槽访问"快速".一些Lisp方言比Common Lisp提供的结构更多.然后从70年代中期开始,为Lisp开发了各种形式的面向对象的表示.大多数结构化对象的表示从结构转移到某种面向对象的Lisp扩展.在80年代流行的是基于类的系统,如Flavors,LOOPS等.基于帧或基于原型的系统(如KEE单元或Object Lisp)也很受欢迎.第一个Macintosh Common Lisp为其所有UI和IO工具使用了Object Lisp.麻省理工学院的Lisp机器基本上到处都使用Flavors.从80年代中期开始,ANSI CL就开发出来了.常见的OO系统是专为Common Lisp:CLOS开发的.它基于Flavors和Loops.在那段时间里,除了实现者找到改进实现的方法并提供浅层CLOS集成之外,大部分时间都没有做真正改进的结构.例如,结构不提供任何数据包.如果有两个4位内容的插槽,则无法指示Common Lisp将两个插槽编码为单个8位内存区域.
作为一个例子,你可以在Lisp机器手册的结构章节(PDF)中看到它的结构比Common Lisp提供的结构复杂得多.其中一些已经出现在70年代的Maclisp中:Maclisp手册中的DEFSTRUCT.
CLOS,Common Lisp对象系统
大多数人会同意CLOS是一个不错的设计.它有时会导致"更大"的代码,主要是因为标识符可能会变长.但是有一些CLOS代码,就像AMOP书中的代码一样,编写得非常好,并展示了它应该如何使用.
随着时间的推移,实现者必须应对开发人员想要使用CLOS的挑战,但也希望拥有结构的"速度".对于"完整"CLOS来说,这更是一项任务,其中包括CLOS几乎标准的元对象协议(MOP).所以实现者提供了一些技巧.在80年代,一些软件使用了一个开关,所以它可以使用结构编译或使用CLOS-CLX(低级Common Lisp X11接口就是一个例子).原因是:在某些计算机和实现上,CLOS比结构慢得多.今天提供这样的编译开关是不寻常的.
如果我今天看一个很好的Common Lisp实现,我希望它几乎在任何地方使用CLOS.STREAM是CLOS类.条件是CLOS类.GUI工具包使用CLOS类.编辑器使用CLOS.它甚至可能将外来类(比如,Objective C类)集成到CLOS中.
在任何非玩具Common Lisp实现中,CLOS将是提供结构化数据,通用行为和一堆其他东西的工具.
正如其他一些答案中所提到的,在某些地方可能不需要CLOS.
Common Lisp可以从函数返回多个值:
(defun calculate-coordinates (ship)
(move-forward ship)
(values (ship-x ship)
(ship-y ship)))
Run Code Online (Sandbox Code Playgroud)
可以将数据存储在闭包中:
(defun create-distance-function (ship x y)
(lambda ()
(point-distance (ship-x ship) (ship-y ship) x y)))
Run Code Online (Sandbox Code Playgroud)
对于配置,可以使用某种列表:
(defship ms-germany :initial-x 0 :initial-y 0)
Run Code Online (Sandbox Code Playgroud)
你可以打赌我会在CLOS中实现船模型.
编写和维护CLOS软件的一个教训是,它需要经过精心设计,CLOS非常强大,可以用它创建非常复杂的软件 - 这种复杂性通常不是一个好主意.重构和简化!幸运的是,对于许多任务,基本的CLOS设施就足够了:DEFCLASS,DEFMETHOD和MAKE-INSTANCE.
CLOS介绍的指针
首先,Richard P. Gabriel有他的CLOS论文供下载.
另见:
的例子defstruct
简短而简单,因为没有什么可说的。Cstruct
很复杂:
由于联合、内联嵌套结构而导致的复杂内存布局在 Cstructs
中也用于其他目的:
访问内存
void*
在Common Lisp 中,defstruct
大致相当于Java 的/C# 的class
:单继承,固定槽,可以用作defmethod
s 中的说明符(类似于virtual
方法)。结构非常适用于嵌套数据结构。
Lisp 程序往往不使用深度嵌套的结构(Lisp 的源代码是主要的例外),因为通常更简单的表示是可能的。