2012-05-11 27 views
4

在Debian上使用SBCL 1.0.56時,使用cl-swank/slime 1:20120420-2(Debian版本號)。這些都是當前版本中不穩定的 。在Debian上使用SLIME在Common Lisp中加載外部軟件包

我一直在加載第三方CL包的問題。在Debian上使用CL的 文檔(實際上Linux上的更一般的CL 使用文檔)粗略,矛盾,並且過時,因此我將總結我所知道的內容。這是我在哪裏。

Debian在 /usr/share/common-lisp/source中安裝二進制包(例如,cl-split-sequence)。在分割序列的情況下,這是 /usr/share/common-lisp/source/cl-split-sequence

的的.asd文件(這裏 /usr/share/common-lisp/source/cl-split-sequence/split-sequence.asd), 其中,按照我的理解,發出指令到執行CL約 版本和依賴關係,看起來像

;;; -*- Lisp -*- mode 
(defpackage #:split-sequence-system (:use #:cl #:asdf)) 
(in-package :split-sequence-system) 

(defsystem :split-sequence 
    :version "20011114.1" 
    :components ((:file "split-sequence"))) 

現在,運行時煤泥,進入下面兩行的REPL 作品沒有問題

(require :split-sequence) 
(split-sequence:SPLIT-SEQUENCE #\, "foo,bar") 

(require :split-sequence)所調用(我認爲)的內部副本 ASBC在SBCL內,大概看起來在split-sequence.asd。此 可能是SBCL特定的,請參閱Common Lisp in Debian Manual Chapter 3 -Libraries。 值得注意的是,這個頁面與我所遇到的任何東西一樣有用和詳細,它經常引用CLC(通用 Lisp控制器),但似乎Debian正在擺脫這種情況。見 Redesign of Common Lisp Controller, 我不完全理解。無論如何,使用CLC的文檔 命令都不適用於我。但是,在Debian上,CLC仍然可用 。此外,用戶郵件列表是死了 - 看到The Clc-users Archives

首次(require :split-sequence)被調用時,它被編譯, 和(我的系統上,可能是Debian相關)所產生的fasl被 放在

~/.cache/common-lisp/sbcl-1.0.56.0.debian-linux-x86/usr/share/common-lisp/source/cl-split-sequence/split-sequence.fasl

iee該文件位於緩存中的文件系統中,該文件系統鏡像原始源的 位置。顯而易見的問題是, 系統如何知道在哪裏尋找軟件包?這是我不是 的一件事。它看起來像搜索路徑應該 /etc/common-lisp/source-registry.conf.d給予,這是航空自衛隊 Debian軟件包的一部分,但最接近的是 01-common-lisp-controller.conf,這僅僅是

(:directory #p"/usr/share/common-lisp/systems/") 

也許這是什麼地方硬連線,但我想知道。

無論如何,一旦這種ASDF文件是在緩存中,它不會被再次編譯, 但REPL沒有看到它煤泥啓動後,除非一個再做 require。現在

,如果我把線

(require :split-sequence) 
(split-sequence:SPLIT-SEQUENCE #\, "foo,bar") 

在一個文件,說seq.lisp,並將其加載到與茜茜的CK REPL,我得到 錯誤和回溯,從

The name "SPLIT-SEQUENCE" does not designate any package. 
    [Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR] 

所以我得出結論,包沒有被正確加載。我試着像變化

(asdf:oos 'asdf:load-op :split-sequence) 

(asdf:load-system :split-sequence) 

,但沒有骰子。古怪,假設我們只是有行

(require :split-sequence) 

在一個文件 - 稱之爲require.lisp的清晰度。然後加載 require.lisp不給一個錯誤,然後鍵入

(split-sequence:SPLIT-SEQUENCE #\, "foo,bar") 

在REPL作品!但是,如果沒有加載require.lisp,則在REPL處鍵入 前一行不起作用。

因此,總而言之,如何成功加載 腳本中的程序包?我也會對上面提到的問題感興趣,大約 ASDF如何找到/usr/share/common-lisp/source/的位置,但是 這是一個側面問題。

回答

4

C-cC-k編譯源文件,然後加載編譯的文件。

Lisp源文件包含定義和調用。文件編譯器遍歷文件併爲其創建代碼。但它不執行它。

如果您的文件包含對REQUIRE的調用,則它在編譯期間不會執行。如果稍後加載編譯的文件,它將被執行。如果文件中的下一個Lisp表單正在使用一些在調用REQUIRE之後可用的包,那麼在編譯期間它就不存在了,因爲REQUIRE尚未執行 - 因此在編譯期間讀取期間出現錯誤。

基本上有兩種辦法,解決:

  • 執行所有必要的REQUIRE操作使用你所需要的功能編譯特定的文件之前。
  • 在編譯期間執行REQUIRE聲明。這就是EVAL-WHEN :COMPILE-TOPLEVEL告訴編譯在編譯期間執行子窗體。

#+:sbcl(foo)表示(富)被讀出,只有當:SBCL存在於列表CL:*FEATURES*的符號。它被使用以便編譯器僅在它是SBCL時才能看到此代碼。

的Common Lisp的代碼編譯需要更多的照顧準備,因爲:

  • 一個文件可以在編譯過程中執行Lisp代碼,從而改變該文件編譯器的行爲。

  • 在源代碼中使用的包(它們是符號的名稱空間)需要文件編譯器的讀者知道。

+0

謝謝Rainer,這是一個非常明確的解釋。我引用的劇本有多少實際上是必要的?如果有什麼,'#+:sbcl'會做什麼? –

+0

回答我自己的問題 - 顯然沒有太多。 (打印(分割序列:SPLIT-SEQUENCE#\,「foo,bar」))('作品。 –

1

我碰到了下面的帖子,Zach Beane's Blog - Making a small Common Lisp project,其中有一個鏈接到http://common-lisp.net/~loliveira/ediware/ediware.lisp

複製在該文件的作品最重要的是代碼。因此,在這個文件加載split-sequence運行C-C C-K粘液,並運行代碼int (split-sequence:SPLIT-SEQUENCE #\, "foo,bar"))

#+:sbcl 
(eval-when (:compile-toplevel :load-toplevel :execute) 
    (require :asdf)) 

(eval-when (:compile-toplevel :load-toplevel :execute) 
    (asdf:oos 'asdf:load-op :split-sequence)) 

(defpackage #:seq 
    (:use #:cl #:split-sequence)) 
(in-package #:seq) 

(print (split-sequence:SPLIT-SEQUENCE #\, "foo,bar")) 

不過,我不知道這些神奇的咒語做。有人會關心解釋,也許在另一個答案?我在回答這個問題時,因爲它是問題的答案,但它不完整,因爲我不明白它爲什麼起作用。我很樂意接受這個腳本的解釋。