使用包的传统观点
有时package(符号命名空间)用于数十甚至数百个文件,可能需要计算包。这在一个文件中可能更简单,当包声明在一个文件中时,可能更容易获得文本概述。例如,文本编辑器的实现可能仅在一个使用大约 100 个文件的包中。另请注意,包实际上是 Common Lisp 中的运行时数据结构,带有 programmer interface。
来自 Java 等其他语言的影响
拥有一个包和一个对应源文件的样式通常来自 Common Lisp 之外,来自通常具有类似 one class = one namespace 之类的对应关系的语言em> = 一个文件。这会导致嵌套目录中存在大量文件,每个文件通常只有一小段代码。
Common Lisp 没有这些限制:方法没有组织在类中,类不是命名空间,文件可以有任何混合定义,...... Lisp 库往往有大包/命名空间和大文件。
结构及其局限性
包
Packages 在 Common Lisp 中是符号的命名空间。这不是一个成熟的模块系统。也没有实际的信息隐藏。符号和导出的符号是有区别的。另请注意,符号作为名称具有多种含义(变量、函数/宏/特殊运算符、类名、槽名、类型、数据对象、包名……),从包中导出符号并没有区别在这些含义之间。另请注意,可以但不建议在一个文件中使用多个包命名空间(例如,使用多个 in-package 表单)。通常,一个文件中只有一个命名空间。这通常由文件顶部某处的in-package 声明。
类
类没有命名空间。通常,类是使用内置的 Common Lisp 对象系统定义的,称为 CLOS。它们捆绑插槽并用于在 CLOS 通用函数中进行调度。但它们不包含它们的方法。
系统
系统不是语言结构。它们是 Common Lisp 的扩展。 系统 的概念由ASDF 等工具提供。系统是一种用于组织一堆文件的工具,这些文件构成了一个库/应用程序及其依赖项。它也是提供功能以在系统上使用操作(编译、加载、交付……)的地方。
???
为了更好地组织代码,可能缺少一些东西。每个项目可能需要稍微不同的方式。
如果需要,我通常会使用文件将相关功能放入一个文件并为系统设置一堆文件。但这可能意味着一个文件实现了多个类和许多功能。我倾向于在实现直接相关代码的部分中组织文件。我可能会在文件顶部描述一些元素(类、函数),但这更多的是局部概述,而不是导出符号的列表。一旦你用它的 IDE 将系统及其文件加载到 Lisp 中,开发环境的目的就是让我查询代码(在哪里?谁使用?使用什么?子/超类?包内容?.. .) 并为此提供浏览器。
还有其他组织代码的方法。例如,使用PROVIDE 和REQUIRE,在语言标准中只对它们进行了非常简单的描述。这些往往会按需引入功能并随时随地创建包结构。
可能需要类似面向对象的协议,它为 CLOS 提供更多结构。
MIT Lisp Machine 操作系统中包和系统的早期使用
70 年代末和 80 年代在麻省理工学院开发的 Lisp Machine 操作系统是为了避免名称冲突和组织代码的系统的早期需求之一。它是在 Lisp Machine Lisp 和后来的 Common Lisp 中开发的。在那里,许多不同的功能(编译器、编辑器、侦听器、检查器、邮件客户端、图形库、文件系统、串行接口、以太网接口、网络代码……)在一个可能有数万个地址空间中运行的符号。包声明通常在相应的系统描述文件中完成(这里我们再次使用 Lisp 的 system 含义作为库或应用程序,用于特定目的的文件集合)或有时在一个单独的文件。包为大型库甚至整个应用程序提供了命名空间。因此,文件、包、系统甚至类(以前称为 Flavor)已经被用来构建软件实现。请参阅 Lisp 机器手册(1984 年的版本),第 29 章,Maintaining Large Systems 和 1984 年的 Kent Pitman 的 MIT AI 备忘录 801:The Description of Large Systems。 Lisp 机器上的系统有 versions 并支持 patching(增量版本更改)。文件也有版本。