在CLISP如何分配存儲器塊,在CLISP
(eq (cons 'a 'b) (cons 'a 'b))
爲假(NIL)
因爲第一(AB)和第二(AB)分配在不同的存儲器中。
和
(eq 'a(car '(a b c)))
爲真(T)
但是,爲什麼呢?
就像兩個(AB)一樣,首先是A和第二個A(car'(a b c))的結果是否必須使用不同的內存?如何在clisp中分配內存塊?
在CLISP如何分配存儲器塊,在CLISP
(eq (cons 'a 'b) (cons 'a 'b))
爲假(NIL)
因爲第一(AB)和第二(AB)分配在不同的存儲器中。
和
(eq 'a(car '(a b c)))
爲真(T)
但是,爲什麼呢?
就像兩個(AB)一樣,首先是A和第二個A(car'(a b c))的結果是否必須使用不同的內存?如何在clisp中分配內存塊?
每次調用CONS將創建一個新的cons單元。這些是不同的對象。
(eq (cons 1 2) (cons 1 2))
- > NIL
符號具有相同的名稱是相同的對象。
(eq 'foo 'foo) -> T
併發症:
符號具有相同的名稱,但在不同的包是不同的對象。
(eq 'bar::foo 'baz::foo) -> NIL
符號使用相同的名稱,沒有包可能是同一對象或沒有。
(eq '#:foo '#:foo) -> NIL
(let ((sym '#:foo))
(eq sym sym))
-> T
CONS創建配對。在您的具體示例中,兩對都包含符號A和B.
通常,您不必擔心在Common Lisp中分配內存塊,而是會創建結構(數組,列表,類,哈希表)。唯一分配內存塊的時候,就是爲了調用另一種語言鏈接的函數。
這是因爲'a被拘留。也就是說,無論何時在代碼中輸入「a」(在第二個示例中,它會出現兩次),它們將解析爲相同的符號。這是因爲讀者將使用INTERN
函數獲得對該符號的引用。 (Hyperspec docs)。
這就是爲什麼(eq 'a 'a)
返回T
。這有一個例外。帶#前綴的符號永遠不會被執行。 GENSYM
使用此功能可確保在編寫宏時獲得唯一的符號。
符號是特殊對象。當Common Lisp首次遇到一個符號時,它將被實現,即創建一個代表該符號的對象並將該符號映射到該對象。對於該符號的所有進一步參考,使用符號名稱作爲關鍵字來檢索該對象。例如,假設Common Lisp在符號爲a
的內存位置0x05處創建了一個對象。對a
的所有進一步參考將指向相同的對象。這意味着(eq 'a 'a)
基本上變成(eq 0x05 0x05
),其評估爲T
。
cons
的情況有所不同。每次調用cons
都會在內存中創建一個新對象。撥打cons
的第一個電話將在位置0x10
處創建一個對象,並在0x20
處創建第二個電話。所以你的第一個比較變成(eq 0x10 0x20)
,它返回nil
。對的組件可能指向相同的對象,但對本身指向不同的位置。
其實,這是不正確的。 #:前綴保證符號不被攔截,因此它們保證不是eq。 – 2011-04-17 14:41:39
@EliasMårtenson:這是正確的,但符號可以存儲在變量中,如果你比較相同的符號,即使它沒有被幹擾,那麼你總是得到T.這個基於身份的「同一性」例如沒有爲數字定義,字符。 – 2011-04-17 15:49:45