in 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中分配内存块?
答案 0 :(得分: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
答案 1 :(得分:3)
这是因为'a是实习生。也就是说,无论何时在代码中键入'a(在第二个示例中,它出现两次),它们将解析为相同的符号。这是因为读者将使用INTERN
函数获得对符号的引用。 (Hyperspec docs)。
这就是(eq 'a 'a)
返回T
的原因。但是有一个例外。前缀为#:的符号永远不会被实现。 GENSYM
使用此功能来保证在编写宏时获得唯一的符号。
答案 2 :(得分:1)
CONS创建对。在您的具体示例中,两对都包含符号A和B.
通常,您不必担心在Common Lisp中分配内存块,而是创建结构(数组,列表,类,哈希表)。你唯一一次分配内存bnlock就是为了调用从另一种语言链接的函数。
答案 3 :(得分:1)
符号是特殊对象。当Common Lisp首次遇到符号时,它会被实现,即创建一个表示符号的对象,并将符号映射到该对象。对于该符号的所有进一步引用,使用符号名称作为键来检索此对象。例如,假设Common Lisp在符号a
的内存位置0x05处创建了一个对象。对a
的所有进一步引用都将指向同一个对象。这意味着(eq 'a 'a)
基本上变为(eq 0x05 0x05
),其评估为T
。
cons
的情况有所不同。每次调用cons
都会在内存中创建一个新对象。第一次调用cons
会在位置0x10
创建一个对象,在0x20
创建第二个调用。因此,您的第一次比较变为(eq 0x10 0x20)
,返回nil
。对的组件可以指向相同的对象,但对本身指向不同的位置。