2011-02-18 35 views
11

我喜歡基於圖像的語言的想法,最近我一直在通過sbcl與Common Lisp一起玩。我已經閱讀了一些關於如何通過保存和加載虛擬機映像的地方,您可以演變在該映像上運行的應用程序或一組應用程序。不斷演變一個lisp圖像

我得到如何將代碼加載到圖像並讓它運行,粘液使這種事情非常好,但我的問題是這樣的:我怎麼能告訴圖像中定義了什麼函數?比方說,我想在運行幾天或幾個月後更新一個函數,但我不記得名字。是否有任何方法可以訪問代碼,甚至只有圖像中定義的函數的名稱?

現在,我將代碼寫入源代碼並通過repl加載,因此我在那裏有一個副本,但它看起來像是一個明顯的功能。

回答

13

Common Lisp的想法是。包是符號的註冊表,用作符號的名稱空間。您可以向Common Lisp詢問所有軟件包的列表。

CL-USER 1 > (list-all-packages) 
(#<The SQL-COMMON package, 0/4 internal, 28/32 external> 
#<The LOOP package, 245/256 internal, 3/4 external> 
#<The COMM package, 0/4 internal, 940/1024 external> 
#<The REG package, 41/64 internal, 0/4 external> 
...) 

每個包存儲在一些數據結構中的實習符號。你可以問Common Lisp哪些符號被封裝在一個包中。

CL-USER 2 > (loop for symbol being 
       each external-symbol in (find-package "COMMON-LISP") 
      collect symbol) 
(MAKE-ARRAY INVOKE-DEBUGGER STRING-TRIM ...) 

爲了方便起見,Common Lisp提供了函數APROPOS和APROPOS-LIST。

CL-USER 3 > (apropos "MAKE-LOCK") 
MP::INTERNAL-MAKE-LOCK (defined) 
MP:MAKE-LOCK (defined) 
WWW-UTILS:MAKE-LOCK (defined) 
MAKE-LOCK 
RESOURCES::MAKE-LOCK (defined) 
MINIPROC:MAKE-LOCK (defined) 

函數,類等使用符號作爲它們的標識符。你也可以問一個符號,它表示哪個函數。

CL-USER 4 > (symbol-function 'www-utils:make-lock) 
#<Function WWW-UTILS:MAKE-LOCK 41E006A69C> 

有時Common Lisp也會記錄函數的定義。然後可以使用FUNCTION-LAMBDA-EXPRESSION函數來檢索'it'。

CL-USER 5 > (defun foo (a) (* (sin a) a)) 
FOO 

CL-USER 6 > (pprint (function-lambda-expression 'foo)) 

(LAMBDA (A) 
    (DECLARE (SYSTEM::SOURCE-LEVEL #<EQ Hash Table{0} 41403151C3>)) 
    (DECLARE (LAMBDA-NAME FOO)) 
    (* (SIN A) A)) 

但通常現在Common Lisp實現不使用記錄的定義,而是記錄每個Lisp構造的源位置。

最常見的Lisp實現可以以實現特定的方式跟蹤源位置。

Common Lisp標準定義了一個函數ED。

CL-USER 7 > (ed 'www-utils:make-lock) 

這調用編輯器(內部或外部),並應打開該函數的源代碼。爲了做到這一點,Common Lisp需要跟蹤每個函數的源位置。接下來,編輯需要訪問該源。有時記錄的位置是絕對路徑/Users/joswig/lisp/utils.lisp。如果編輯想要打開該文件,則應該可以訪問該文件。但是也可以使用邏輯路徑名稱,如http:server; utils.lisp。然後將其轉換爲真實的物理路徑名。此翻譯可以稍後進行配置。因此,可以將Lisp移動到具有不同路徑名的其他計算機上,配置邏輯路徑名HTTP,然後Lisp仍然可以找到所有源代碼,即使它位於具有不同文件系統結構的不同計算機上。所以,要使它工作可能需要一些配置。但它是一個非常有用的功能,它被廣泛使用。

源代碼的記錄以及源位置的記錄如何工作取決於實現,它是相應Lisp與其開發環境相結合的一個特性。 更好 Lisp實現在這方面有很多功能。

5

您還可以使用做符號或做外部的符號,如果你喜歡:

例如:

>> (do-external-symbols (s (find-package :foo-package)) (print s)) 

FOO-PACKAGE:XXX 
FOO-PACKAGE:YYY 
FOO-PACKAGE:ZZZ 
NIL 

其中XXX,YYY & ZZZ是包中的所有外部符號:foo-包。