2011-04-17 53 views
3

在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中分配内存块?

回答

4

每次调用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 
+0

其实,这是不正确的。 #:前缀保证符号不被拦截,因此它们保证不是eq。 – 2011-04-17 14:41:39

+0

@EliasMårtenson:这是正确的,但符号可以存储在变量中,如果你比较相同的符号,即使它没有被干扰,那么你总是得到T.这个基于身份的“同一性”例如没有为数字定义,字符。 – 2011-04-17 15:49:45

1

CONS创建配对。在您的具体示例中,两对都包含符号A和B.

通常,您不必担心在Common Lisp中分配内存块,而是会创建结构(数组,列表,类,哈希表)。唯一分配内存块的时候,就是为了调用另一种语言链接的函数。

3

这是因为'a被拘留。也就是说,无论何时在代码中输入“a”(在第二个示例中,它会出现两次),它们将解析为相同的符号。这是因为读者将使用INTERN函数获得对该符号的引用。 (Hyperspec docs)。

这就是为什么(eq 'a 'a)返回T。这有一个例外。带#前缀的符号永远不会被执行。 GENSYM使用此功能可确保在编写宏时获得唯一的符号。

1

符号是特殊对象。当Common Lisp首次遇到一个符号时,它将被实现,即创建一个代表该符号的对象并将该符号映射到该对象。对于该符号的所有进一步参考,使用符号名称作为关键字来检索该对象。例如,假设Common Lisp在符号为a的内存位置0x05处创建了一个对象。对a的所有进一步参考将指向相同的对象。这意味着(eq 'a 'a)基本上变成(eq 0x05 0x05),其评估为T

cons的情况有所不同。每次调用cons都会在内存中创建一个新对象。拨打cons的第一个电话将在位置0x10处创建一个对象,并在0x20处创建第二个电话。所以你的第一个比较变成(eq 0x10 0x20),它返回nil。对的组件可能指向相同的对象,但对本身指向不同的位置。