Common lisp conses规范
维基百科关于的页面上说aCommon lisp conses规范,common-lisp,Common Lisp,维基百科关于的页面上说acons是一对指针 以下代码似乎证实了这一点: (progn) (setq a’(1.2)) (环境运输及工务局局长) (setf(b车)10) (打印a) 对该表单的评估给出了cons(10.2)。设置b的car会更改a的car。你可以在厨房里试试 该行为在中的定义是什么 (我已经阅读了一些文本,但找不到指向该行为的部分插针。) 有趣的是,conses上的Wikipedia页面上说“cons构造了包含两个值或指向值的指针的内存对象”。如果atom 1将直接存储在con
cons
是一对指针
以下代码似乎证实了这一点:
(progn)
(setq a’(1.2))
(环境运输及工务局局长)
(setf(b车)10)
(打印a)
对该表单的评估给出了cons(10.2)
。设置b的car
会更改a的car
。你可以在厨房里试试
该行为在中的定义是什么
(我已经阅读了一些文本,但找不到指向该行为的部分插针。)
有趣的是,conses上的Wikipedia页面上说“cons
构造了包含两个值或指向值的指针的内存对象”。如果atom 1将直接存储在cons对象中,那么更改b
不会更改a
,对吗
我在上面假设a
和b
持有cons对象,而不是指向conse的指针。
即使实际的lisp实现与指针一起工作,这也不应该在repl级别上可见,或者应该根据规范进行吗?当假定a
和b
持有指向相同cons
的指针时,可以实现类似的效果。
考虑到
,即通过重复应用cons
构建列表,支持cons由符号值中的指针表示的假设
以下两种形式是等效的:
(let((a'(1)))
(setq b(cons 2 a)))
(setq b'(21))
首先,您的代码无效,因为不允许您修改常量列表。应该是:
(progn
(setq a (cons 1 2))
(setq b a)
(setf (car b) 10)
(print a))
当您执行类似于(setq b a)
的赋值时,它会将b
的值设置为与a
的值相同。SETQ
的规范没有说明如何复制该值,因此这两个变量包含相同的值,在本例中为cons单元格
设置cons单元格的car会修改该对象——同样,不会进行复制。因此,您将通过引用cons单元格的任何变量或任何其他引用(它可能位于结构插槽、数组元素、另一个cons单元格等)看到更改
我认为规范从来没有真正出来说这些东西都是一样的,它只是隐含在我们传递抽象对象的事实中,除非调用明确定义的函数(例如,COPY-TREE
),否则不会进行复制
规范中没有提到指针,但这通常是在封面下发生的事情。cons单元类似于C结构:
typedef struct cons {
lisp_object car,
lisp_object cdr
} cons;
lisp_object
可能是各种类型的联合体(一些直接类型用于FIXNUM
之类的对象,而指针用于其他类型)。当变量包含cons
时,它实际上包含指向上述结构的指针,赋值复制指针,而不是结构。因此Lisp代码类似于C代码,如:
cons *a = make_cons(1, 2);
cons *b = a;
b->car = 10;
printf("%d\n", a->car);
首先,您的代码无效,因为您不允许修改常量列表。应该是:
(progn
(setq a (cons 1 2))
(setq b a)
(setf (car b) 10)
(print a))
当您执行类似于(setq b a)
的赋值时,它会将b
的值设置为与a
的值相同。SETQ
的规范没有说明如何复制该值,因此这两个变量包含相同的值,在本例中为cons单元格
设置cons单元格的car会修改该对象——同样,不会进行复制。因此,您将通过引用cons单元格的任何变量或任何其他引用(它可能位于结构插槽、数组元素、另一个cons单元格等)看到更改
我认为规范从来没有真正出来说这些东西都是一样的,它只是隐含在我们传递抽象对象的事实中,除非调用明确定义的函数(例如,COPY-TREE
),否则不会进行复制
规范中没有提到指针,但这通常是在封面下发生的事情。cons单元类似于C结构:
typedef struct cons {
lisp_object car,
lisp_object cdr
} cons;
lisp_object
可能是各种类型的联合体(一些直接类型用于FIXNUM
之类的对象,而指针用于其他类型)。当变量包含cons
时,它实际上包含指向上述结构的指针,赋值复制指针,而不是结构。因此Lisp代码类似于C代码,如:
cons *a = make_cons(1, 2);
cons *b = a;
b->car = 10;
printf("%d\n", a->car);
设置b的轿厢会改变a的轿厢
您没有设置b
的car
。您正在设置由b
和a
引用的同一cons单元格的car
CL-USER 1 > (let (a b)
(setq a (cons 1 2))
(setq b a)
(eq a b))
T
说明:
- 我们有变量
a
和b
(cons 1 2)
返回cons单元格
(setq a(cons 1 2))
将a设置为(cons 1 2)
的结果,即cons单元格
(setq b a)
计算a
,它返回cons单元格上方并将b
设置为该cons单元格
理解的关键是,变量和函数的求值返回非原语(即原语数字、字符等除外)对象本身,而不是副本
我在上面假设a和b持有cons对象,而不是指向cons的指针
那是错误的a
和b
是变量,它们只指向同一个单元格
“cons构造包含两个值或指向值的指针的内存对象”
在一个普通的Lisp实现中,像小数字(fixNum)这样的东西可能直接存储在cons单元中。人们无法通过身份(使用EQ
)可靠地比较数字,必须进行数字比较(EQL
,=
,…)