2008-12-06 59 views
7

我試圖在OS X上使用SLIME與OpenMCL(現在稱爲CCL)運行光線跟蹤代碼表格Paul Graham的ANSI Common Lisp。在該代碼,還有它的值是一個結構定義的常量,當我打電話或者煤泥編譯並加載文件煤泥編譯defun定義上使用恆定的任何功能,我得到一個錯誤消息:「No MAKE LOAD-FORM」錯誤與OpenMCL Common Lisp

否MAKE-LOAD-FORM方法是用於定義#S (POINT:X 0 :Y 0 位:Z 200)[條件式的 SIMPLE-ERROR]

我發現a post解釋相關問題灰燼和another one感嘆,但需要添加到代碼來談判這方面的OpenMCL?

回答

8

當STRUCTURE-OBJECT(和一些其他類型的對象)作爲文字常量對象出現時,COMPILE-FILE處理的代碼中的常量對象需要知道如何安排該對象,當加載結果二進制文件時,會創建一個「等效」對象。 「等價」有許多可能的定義:有時,加載對象的組件與其他對象共享結構很重要,有時以某種方式進行初始化非常重要,有時這些事情都不重要。爲了確定如何重新創建常量對象,COMPILE-FILE調用通用函數MAKE-LOAD-FORM;這個行爲應該在任何CL參考或教程中描述。 (參考或教程還應該注意,實現不能定義默認MAKE-LOAD-FORM方法將適用於結構CLASS或標準類的所有實例,並且還應該注意到,MAKE-LOAD-FORM-SAVING -SLOTS是一個方便的功能MAKE-LOAD-FORM方法的對象在初始化時使用並不需要很複雜,例如:

(defmethod make-load-form ((p point) &optional env) 
    (declare (ignore env)) 
    (make-load-form-saving-slots p)) 

注意,這種方法在編譯時定義,所以COMPILE-FILE可以調用它來確定如何保存常量POINT對象

這些都不是CCL特有的,可能是哪些東西是常量,文字對象以及哪些不是東西。

在代碼等:

(defconstant a-point (make-point :x 0 :y 0 :z 200)) 

(defun return-a-point() a-point) 

編譯器的允許的(但不是必需的)來代替A-POINT的值在函數RETURN-A-POINT的引用。 (如果編譯器這樣做,這將 意味着有一個在代碼中的字面/恆壓點對象進行編譯,編譯文件將需要調用MAKE-LOAD-FORM確定對象應如何保存和載入,如果編譯器不會做這個替代,然後進行-LOAD-FORM不需要在這個例子中被調用。)

是否實現執行這種替代或不可達的實現。該規範還未說明DEFCONSTANT表單中的值表單是在編譯時,加載時還是兩者都計算的,並指出必須小心(由用戶)執行以確保表達式始終評估爲相同的價值。

CCL通常嘗試計算在編譯時的DEFCONSTANT值形式,並且是相當積極約代替對它們的引用名爲常數的值;在某些情況下,這意味着必須定義常量值的類的MAKE-LOAD-FORM方法。其他實現可能不太願意爲某些類型的對象進行這種替換。兩種策略都是正確的,便攜式代碼無法假定正在遵循哪種策略(儘管很多人認爲便攜式代碼確實會做出這樣的假設)。

由DEFCONSTANT定義的事物的不同處理看起來像是這種類型的最可能原因(意想不到的打電話給MAKE-LOAD-FORM,這是沒有人打算定義的)。人們可以通過做避免這些問題的方式,應該是便攜式:

(defconstant a-point (make-point :x 0 :y 0 :z 200)) 

(defun return-a-point() (load-time-value (symbol-value 'a-point))) 

這將產生類似的效果,以簡單地允許想要這麼做的實現(如CCL做)做定替換,但使用LOAD-TIME-VALUE將確保僅在加載時評估常量值(並且不會涉及MAKE-LOAD-FORM)。

+0

我假設你打算打電話給`你的DEFCONSTANT形式的RETURN-A-POINT? – 2012-08-11 14:57:58