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 的命名。參見此處以獲得相互依賴、多系統項目的一個例子。

參見[編輯 | 編輯原始碼]