4

我目前正试图围绕包、系统和公司。

我现在已经阅读了包、系统、模块、库 - WTF?几次,我想我仍然很难把它做好。

如果我只是想将 Lisp 源文件拆分为两个文件,其中一个应“使用”另一个 - 我该怎么做?我需要为此建立一个系统吗?我应该使用模块吗?……?我来自 Node.js 背景,你可以简单地说

var foo = require('./foo');

获取对文件中导出内容的引用foo.js。在 Lisp 中与此最接近的等价物是什么?

我知道ASDF用于系统,并且它被捆绑为Quicklisp的一部分,至少根据其文档:

ASDF 捆绑了所有最新版本的活动 Common Lisp 实现以及 quicklisp […]

好的,Quicklisp 是用于库的,但它们的关系是什么?Quicklisp 是不是其他语言中的“包管理器”之类的东西?如果是这样,那么 ASDF 究竟提供了什么?

很抱歉有这么多问题,但我认为它只是说明了我必须理解如何构建 Lisp 应用程序的麻烦。任何帮助将不胜感激 :-)

4

2 回答 2

8

系统

对于构建大型系统,请使用系统管理工具。一个“免费”的是ASDF

您将需要一个系统声明,其中列出了您的库或应用程序的各个部分。通常它进入一个自己的文件。然后你加载一个系统或编译一个系统。应该有教程如何做到这一点。

一个简单的 Lisp 系统可能有以下文件:

  • 一个系统文件,描述系统、它的部件和任何其他需要的东西(其他系统)
  • 描述使用的命名空间的包文件
  • 一个基本的工具文件(例如宏使用的函数)
  • 列出宏的宏文件(用于在软件的其余部分之前编译/加载它们)
  • 一个或多个其他具有功能的文件。

Quicklisp 独立于此。它是一个软件分发工具。

快速编译和加载文件

但是您也可以在没有系统工具的情况下以老式方式编译和加载文件:

(defparameter *files*
  '("/yourdir/foo.lisp" "/yourdir/bar.lisp"))

(defun compile-foobar ()
  (mapc #'compile-file *files*))

(defun load-foobar ()
  (mapc #'load *files*))

(defun compile-and-load ()
  (mapc (lambda (file)
           (load (compile-file file)))
        *files*))

实际上可能还有更多内容,但通常就足够了。编写自己的构建工具应该很容易。一个典型的系统工具将提供更多功能,以结构化方式构建更复杂的软件。这些工具的许多想法至少可以追溯到 35 年前。例如,参见Lisp Machine 手册,这里是 1984 年的版本,维护大型系统一章。

档案的作用

请注意,在普通的 Common Lisp 中,文件的角色及其语义并不是很复杂。

文件不是命名空间,它/子类对象相关联,它不是模块。您可以根据需要在文件中混合 Lisp 结构。文件可以是任意大的(例如,一个复杂的库有一个版本,它作为具有 30000 行的单个源文件提供)。在标准语义中,文件发挥作用的唯一真实位置是编译文件时。编译文件有什么副作用?编译器可以做哪些优化?

除此之外,假设开发环境提供诸如加载和编译文件组(即系统)之类的服务,提供编译错误的概述,记录定义的源位置,可以定位定义等等。像ASDF这样的工具处理系统部分。

于 2015-06-12T17:25:06.877 回答
2

Common Lisp 中有一个require函数,但它已被弃用。如果您只是想将代码拆分为一个或多个部分,以便在 REPL 中交互地使用它,您可以将代码放在不同的文件中,然后分别放在load每个文件中。相反,如果您想编写一个完整的 lisp 项目,我发现quickproject包非常有用,它为创建新包提供了一个简单的起点。

于 2015-06-12T16:25:28.320 回答