Lisp 中 C 结构体的惯用等效项是什么?
在 C 类型语言中,从一开始以及每本介绍性书籍都非常强调结构/记录和对象。然后,它们的完整系统是围绕管理这些结构、它们的相互关系和继承而设计的。
在 Lisp 文档中,您通常可以找到 1-2 页有关 Lisp 如何“也”具有 defstruct 的内容,这是一个简单的示例,通常就是这样。而且,结构的嵌套根本没有被提及。
对于来自 C 背景的人来说,首先似乎分层组织不同数据类型并不是 Lisp 中的首选方法,但除了 CLOS 之外,CLOS 是一个成熟的对象系统,如果您只想要结构,则太复杂,而且除了塞满所有内容之外到列表中,没有明显的方法来转移您的 C 结构知识。
最类似于 C 结构体的分层组织数据的惯用 Lisp 方式是什么?
--
我认为我的问题的总结答案是:对于初学者学习的目的,可以使用 defstruct 和/或 plists,尽管是“遗留功能”,因为它们与 C 结构最相似,但它们在很大程度上已被更灵活的 defclass/CLOS,现在大多数 Lisp 程序都使用它。
这是我关于 SO 的第一个问题,所以感谢大家花时间回答这个问题。
In C-type languages, there is a strong emphasis on structs/records and objects from the very beginning and in every introductory book. Then, their complete systems are designed around managing such structs, their mutual relations and inheritance.
In Lisp documentation, you can usually find 1-2 pages about how Lisp "also" has a defstruct, a simple example, and thats usually it. Also, nesting of structures is never mentioned at all.
For someone coming from a C background, it first seems that organizing different data types hierarchically isnt the preferred method in Lisp, but apart from CLOS, which is a full blown object system and too complicated if you just want structs, and apart from craming everything into lists, there isnt an apparent way to transfer your C struct knowledge.
What is the idiomatic Lisp way of hierarchically organizing data which most resembles C structs?
--
I think the summary answer to my question would be: For beginner learning purposes, defstruct and/or plists, although "legacy features", can be used, since they most closely resemble C structs, but that they have been largerly superseded by the more flexible defclass/CLOS, which what most Lisp programs use today.
This was my first question on SO, so thanks everyone for your time answering it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用 CLOS。它并不复杂。
否则使用结构。
如果您对如何使用它们有具体疑问,请直接询问。
类似的东西最终会导致像CLIM中的矩形(Common Lisp 接口管理器)。
历史
稍微扩展一下:历史上“结构”曾用于一些低级别的情况。结构具有单一继承性,并且槽访问是“快速”的。有些 Lisp 方言比 Common Lisp 提供的结构更多。然后从 70 年代中期开始,Lisp 开发了各种形式的面向对象表示形式。大多数结构化对象的表示形式从结构转移到某种面向对象的 Lisp 扩展。 80 年代流行的是基于类的系统,例如 Flavors、LOOPS 等。基于框架或基于原型的系统(例如 KEE Units 或 Object Lisp)也很流行。第一个 Macintosh Common Lisp 将 Object Lisp 用于其所有 UI 和 IO 设施。 MIT Lisp 机器基本上到处都使用了 Flavors。从 80 年代中期开始,ANSI CL 被开发出来。专门为 Common Lisp 开发了一个通用的面向对象系统:CLOS。它基于风味和循环。在那段时间里,除了实施者寻找改进实施的方法并提供浅层 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 类。 CONDITION 是 CLOS 类。 GUI 工具包使用 CLOS 类。小编使用的是CLOS。它甚至可能将外部类(例如 Objective C 类)集成到 CLOS 中。
在任何非玩具 Common Lisp 实现中,CLOS 都将成为提供结构化数据、通用行为和许多其他内容的工具。
正如其他一些答案中提到的,在某些地方可能不需要 CLOS。
Common Lisp 可以从一个函数返回多个值:
可以在闭包中存储数据:
对于配置,可以使用某种列表:
你可以打赌我会在 CLOS 中实现船舶模型。
编写和维护 CLOS 软件的一个教训是,它需要精心设计,而且 CLOS 非常强大,人们可以用它创建非常复杂的软件 - 这种复杂性通常不是一个好主意。重构并简化!幸运的是,对于许多任务来说,基本的 CLOS 工具就足够了:DEFCLASS、DEFMETHOD 和 MAKE-INSTANCE。
CLOS 介绍指南
首先,Richard P. Gabriel 有他的CLOS 论文< /a> 下载。
另请参阅:
Use CLOS. It isn't complicated.
Otherwise use structures.
If you have a specific question how to use them, then just ask.
Stuff like that eventually leads to interfaces like Rectangles in CLIM (the Common Lisp Interface Manager).
History
To expand on it a bit: Historically 'structures' have been used in some low-level situations. Structures have single inheritance and slot access is 'fast'. Some Lisp dialects have more to structures than what Common Lisp offers. Then from the mid-70s on various forms of object-oriented representations have been developed for Lisp. Most of the representation of structured objects moved from structures to some kind of object-oriented Lisp extension. Popular during the 80s were class-based systems like Flavors, LOOPS and others. Frame-based or prototype-based systems like KEE Units or Object Lisp were also popular. The first Macintosh Common Lisp used Object Lisp for all its UI and IO facilities. The MIT Lisp machine used Flavors basically everywhere. Starting in the mid 80s ANSI CL was developed. A common OO-system was developed especially for Common Lisp: CLOS. It was based on Flavors and Loops. During that time mostly nothing was done to really improve structures - besides implementors finding ways to improve the implementation and providing a shallow CLOS integration. For example structures don't provide any packing of data. If there are two slots of 4 bits content, there is no way to instruct Common Lisp to encode both slots into a single 8 bit memory region.
As an example you can see in the Lisp Machine Manual, chapter on structures (PDF), that it had much more complex structures than what Common Lisp provides. Some of that was already present in Maclisp in the 70s: DEFSTRUCT in the Maclisp manual.
CLOS, the Common Lisp Object System
Most people would agree that CLOS is a nice design. It sometimes leads to 'larger' code, mostly because identifiers can get long. But there is some CLOS code, like the one in the AMOP book, that is really nicely written and shows how it is supposed to be used.
Over time implementors had to deal with the challenge that developers wanted to use CLOS, but also wanted to have the 'speed' of structures. Which is even more a task with the 'full' CLOS, which includes the almost standard Meta Object Protocol (MOP) for CLOS. So there are some tricks that implementors provide. During the 80s some software used a switch, so it could compiled using structures or using CLOS - CLX (the low-level Common Lisp X11 interface was an example). The reason: on some computers and implementations CLOS was much slower than structures. Today it would be unusual to provide such a compilation switch.
If I look today at a good Common Lisp implementation, I would expect that it uses CLOS almost everywhere. STREAMs are CLOS classes. CONDITIONs are CLOS classes. The GUI toolkit uses CLOS classes. The editor uses CLOS. It might even integrate foreign classes (say, Objective C classes) into CLOS.
In any non-toy Common Lisp implementation CLOS will be the tool to provide structured data, generic behavior and a bunch of other things.
As mentioned in some of the other answers, in some places CLOS might not be needed.
Common Lisp can return more than one value from a function:
One can store data in closures:
For configuration one can use some kind of lists:
You can bet that I would implement the ship model in CLOS.
A lesson from writing and maintaining CLOS software is that it needs to be carefully designed and CLOS is so powerful that one can create really complex software with it - a complexity which is often not a good idea. Refactor and simplify! Fortunately, for many tasks basic CLOS facilities are sufficient: DEFCLASS, DEFMETHOD and MAKE-INSTANCE.
Pointers to CLOS introductions
For a start, Richard P. Gabriel has his CLOS papers for download.
Also see:
defstruct
的示例简短而简单,因为没有太多可说的。 C 的结构很复杂:在 C 中,
结构
还用于其他目的:访问内存
void*
在 Common Lisp 中,
defstruct
大致相当于 Java/C# 的class
:单继承、固定槽,可以用作中的说明符defmethod
(类似于虚拟
方法)。结构完全适用于嵌套数据结构。Lisp 程序往往不使用深层嵌套结构(Lisp 的源代码是主要例外),因为通常可以使用更简单的表示。
Examples with
defstruct
are short and simple because there isn't much to say about them. C'sstruct
s are complicated:complicated memory layout due to unions, inline nested structures
In C,
structs
are also used for other purposes:to access memory
void*
In Common Lisp,
defstruct
is roughly equivalent to Java's/C#'sclass
: single inheritance, fixed slots, can be used as specifiers indefmethod
s (analogous tovirtual
methods). Structures are perfectly usable for nested data structures.Lisp programs tend not to use deeply nested structures (Lisp's source code being the primary exception) due to that often more simple representations are possible.
属性列表 (plist)
Property Lists (plists)
我认为 C 结构体的惯用用法是不需要首先将数据存储在结构体中。我想说至少 50% 的 C 风格代码我已经移植到 Lisp,而不是将数据存储在某种复杂的结构中,我只是计算我想要计算的内容。 C 需要结构体来临时存储所有内容,因为它的表达式非常弱。
如果您有一些 C 风格代码的具体示例,我相信我们可以演示在 Lisp 中实现它的惯用方法。
除此之外,请记住 Lisp 的 s-exp 是分层数据。例如,Lisp 中的 if 表达式本身就是分层数据。
I think the idiomatic equivalent of a C struct is to not need to store the data in structs in the first place. I'd say at least 50% of the C-style code I've ported to Lisp, rather than storing the data in some elaborate structure, I just compute what it is I want to compute. C needs structs to store everything temporarily because its expressions are so weak.
If you a specific example of some C-style code, I'm sure we could demonstrate an idiomatic way to implement it in Lisp.
Beyond that, remember that Lisp's s-exps are hierarchical data. An
if
expression in Lisp, for example, is itself hierarchical data.我认为这就是我正在寻找的东西,可以在这里找到:
http: //cl-cookbook.sourceforge.net/clos-tutorial/index.html
y
I think this is kind of what I was looking for, can be found here:
http://cl-cookbook.sourceforge.net/clos-tutorial/index.html
y
为什么不使用哈希表?结构中的每个成员都可以是哈希表中的键。
Why not use hash tables? Every member in the struct can be a key in a hash table.