Common Lisp

来自 Arch Linux 中文维基

Common Lisp 是一种高度动态的多范例语言,强调交互性和性能。完全标准化后,其有许多独立的实现可供选择。

安装[编辑 | 编辑源代码]

sbcl (http://www.sbcl.org/) 是最受欢迎的 FOSS 实现,总体跨软件生态兼容度最高。其编译器可生成原生的机器码。该项目每月发布更新。

配置文件是 ~/.sbclrc,使用 Lisp 语言编写。但是,基于您选择的依赖管理策略,您可能用不上它。

替代实现[编辑 | 编辑源代码]

有许多可用的替代实现。除下述外,有两大商用 Lisp 实现:Allegro 和 LispWorks,但它们附有严格的许可条款,也未打包到 Arch Linux 生态中。

活跃[编辑 | 编辑源代码]

这些功能与现代工具可无缝配合,可用于大型项目。

  • ABCL — Armed Bear Common Lisp:在 Java 虚拟机上运行。
https://common-lisp.net/project/armedbear/ || abclAUR
  • CCL — Clozure Common Lisp:基于 Open Machintosh Common Lisp,以极快的编译速度闻名。
https://ccl.clozure.com/ || cclAUR
  • Clasp — Clasp:一种较新的 Common Lisp 实现,可与 C++ 库互操作,并借助 LLVM 编译至机器码。
https://clasp-developers.github.io/ || clasp-clAUR
  • ECL — Embeddable Common Lisp:可编译至 C 代码,从而提供良好的 C 集成和嵌入性。
https://common-lisp.net/project/ecl/ || ecl

历史[编辑 | 编辑源代码]

尽管有相应软件包,但库和工具的兼容性令人怀疑,而且有些实现已不再受到积极维护。

  • CLISP — ANSI Common Lisp 解释器、编译器及调试器:提供良好的 C 集成和嵌入性。
https://www.gnu.org/software/clisp/ || clisp
  • CMUCL — CMU Common Lisp:一个仅 POSIX 的实现,最初在卡内基梅隆大学开发。
https://gitlab.common-lisp.net/cmucl/cmucl/-/wikis/home || cmucl
  • GCL — GNU Common Lisp:80 年代 Kyoto Common Lisp 的后代,ECL 的兄弟。
https://www.gnu.org/software/gcl/ || gclAUR
  • MKCL — Mankai Common Lisp:也是 Kyoto Common Lisp 的后代。
https://mkcl.common-lisp.dev/ || mkcl-gitAUR

依赖管理[编辑 | 编辑源代码]

Quicklisp[编辑 | 编辑源代码]

Quicklisp 是这样一个系统:获取库,并将其加载到 Common Lisp 程序中。默认情况下,本机所有程序共用单一全局软件包缓存。而且,Quicklisp 从一个保守更新的仓库中提取软件包,该仓库也叫做 Quicklisp(可能引起混淆)。

安装 quicklisp 包后,可通过以下方式,将其作为一个特定编译器注册:

> sbcl --load /usr/share/quicklisp/quicklisp.lisp
* (quicklisp-quickstart:install)
* (ql:add-to-init-file)

在此之后,可以在以后所有的 REPL 会话中使用 (ql:quickload "foo") 来加载一个依赖项,必要时会下载该依赖项。

要更新通过 Quicklisp 安装的所有包,在 REPL 中运行以下命令:

(ql:update-all-dists)
注意: 一般来说,Quicklisp 假定您创建的所有 Common Lisp 项目都在 ~/common-lisp/ 目录下。

Ultralisp[编辑 | 编辑源代码]

Ultralisp 是一个替代 Quicklisp 的仓库,提供所有包的滚动更新,原则上与 Github 最新发布保持一致。

要将其注册,在 REPL 中运行:

(ql-dist:install-dist "http://dist.ultralisp.org/" :prompt nil)

如果您 ql:quickload 的包在 Ultralisp 中有较新版本,该包将从 Ultralisp 而非 Quicklisp 加载。

Qlot[编辑 | 编辑源代码]

或者,若您需要项目本地依赖,可以采用 Qlot (qlotAUR)。

安装后,项目仓库可以通过以下命令初始化:

qlot init

自定义依赖[编辑 | 编辑源代码]

使用 Qlot、所有自定义依赖的位置都记录在 qlfile 中。例如,要声明使用 Ultralisp,只需添加:

dist http://dist.ultralisp.org

或指定本地依赖:

local foobar /home/you/code/common-lisp/foobar

参见 Qlot 的 README 以了解更多选项。

要安装已经声明的依赖,运行:

qlot install

启用 REPL[编辑 | 编辑源代码]

要在当前 Qlot 环境中加载 REPL,请运行:

qlot exec sbcl

使用 Sly/Slime 的 Emacs 用户,考虑这样配置编辑器内 REPL 的启动方式:

(setq sly-default-lisp 'qlot-sbcl
      sly-lisp-implementations '((qlot-sbcl ("qlot" "exec" "sbcl") :coding-system utf-8-unix)))

Slime 类似,进行必要的调整即可。

开发环境[编辑 | 编辑源代码]

Emacs[编辑 | 编辑源代码]

Common Lisp 开发常常通过 Emacs 完成:借助 slime 或较新的 sly。两者都被社区广泛采用且使用方法类似。

Lem[编辑 | 编辑源代码]

Lem (lem-editor-gitAUR) 是一个较新的 Emacs 风格编辑器,但是完全由 Common Lisp 编写和配置。其拥有终端和图形化前端,并支持许多语言。

提示[编辑 | 编辑源代码]

管理 Init 文件[编辑 | 编辑源代码]

库的作者经常使用多个编译器实现来测试他们的代码。但是,每个实现都有各自不同的 init 文件,例如 .sbclrc.eclrc。但这些文件的内容往往是相同的:与其为每个编译器手写这些文件,不如创建一个主文件,并将其他文件链接到该文件。例如,如果您考虑 .sbclrc 成为您的 "主配置",然后:

ln -s /home/you/.sbclrc .eclrc
ln -s /home/you/.sbclrc .abclrc

等等。这些主要 init 文件是:

~/.sbclrc          # for SBCL
~/.abclrc          # for ABCL
~/.ccl-init.lisp   # for CCL
~/.clasprc         # for CLASP
~/.eclrc           # for ECL
~/.clisprc.lisp    # for CLISP
~/.cmucl-init.lisp # for CMUCL
~/.mkclrc          # for MKCL
~/.clinit.cl       # for Allegro

疑难解答[编辑 | 编辑源代码]

Quicklisp 不能加载本地项目[编辑 | 编辑源代码]

(ql:quickload "...") 用于加载外部依赖项和本地项目。但若本地项目不位于 ~/common-lisp/,将无法加载。项目甚至可能被从在线平台上删除,如果已经发布。

实际上,Quicklisp 只是获取和整理软件包。它内部使用 ASDF 构建系统,以实际加载这些包。也可以通过 (asdf:load-system "foo"),默认情况下,ASDF 只在 ~/common-lisp/ 中寻找本地项目。

虽然可以配置,但更简单的方法是使用符号链接:

ln -s /home/you/code/common-lisp/ common-lisp
注意: 如果使用 Qlot,则不需要上述符号链接。只要您执行 qlot install,然后 (asdf:load-package "foo") 即可。

什么是项目、系统、软件包?[编辑 | 编辑源代码]

本文其余部分使用的“包”一词是其他编程语言通常使用的“库 ”的同义词。不过,虽然 Common Lisp 在 90 年代中期就已标准化,但其最早的形式却是在 80 年代出现的,因此涉及项目管理的术语也有所不同。实质上:

  • 项目:一组系统。有时在其他语言中被称为“命名空间”。
  • 系统:一组包。既可代表库,也可代表 “可执行文件”。
  • 软件包:一组函数和类型定义。在其他语言中通常称为“模块”,但可跨多个文件。

如您所见,在其他地方通常被称为库的东西,在 Common Lisp 中被称为“系统”。因此有 asdf:load-system 的命名。参见此处以获得相互依赖、多系统项目的一个例子。

参见[编辑 | 编辑源代码]