Common lisp conses规范

Common 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

维基百科关于的页面上说a
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
=
,…)