Lisp 与x27之间的差异;(())和(cons null)
我对scheme中的“(())和(cons null)之间的区别感到困惑 下面的代码显示Lisp 与x27之间的差异;(())和(cons null),lisp,scheme,Lisp,Scheme,我对scheme中的“(())和(cons null)之间的区别感到困惑 下面的代码显示b和c是完全相同的东西 (define (dup2 x) (let ((d '(()))) (set-car! d (car x)) (set-cdr! d (cdr x)) d)) (define a '(1 2)) (define b (dup2 a)) (define c (dup2 a)) (set-car! b 2) > c ;; --> (2 2)
b
和c
是完全相同的东西
(define (dup2 x)
(let ((d '(())))
(set-car! d (car x))
(set-cdr! d (cdr x))
d))
(define a '(1 2))
(define b (dup2 a))
(define c (dup2 a))
(set-car! b 2)
> c ;; --> (2 2)
但是,当我使用dup
而不是dup2
时:
(define (dup x)
(let ((d (cons null null)))
(set-car! d (car x))
(set-cdr! d (cdr x))
d))
(define a '(1 2))
(define b (dup a))
(define c (dup a))
(set-car! b 2)
> c ;; --> (1 2)
变量
b
和c
是不同的。我做了一些实验,但我还不明白。数据文本,如'(())
,应该是只读的,并使用set car修改它代码>或设置cdr代码>具有未定义的行为。对于可预测的行为,如果要使用设置汽车,请使用(cons'()'())
版本代码>或设置cdr代码>在上面
特别是,cons
创建一个新的cons单元格,而数据文本通常不会
不过,为了实现dup
,为什么要使用set car代码>和设置cdr代码>无论如何?直接使用cons
:
(define (dup x)
(cons (car x) (cdr x)))
数据文本,如”(())
,是只读的,可以使用set car修改它代码>或设置cdr代码>具有未定义的行为。对于可预测的行为,如果要使用设置汽车,请使用(cons'()'())
版本代码>或设置cdr代码>在上面
特别是,cons
创建一个新的cons单元格,而数据文本通常不会
不过,为了实现dup
,为什么要使用set car代码>和设置cdr代码>无论如何?直接使用cons
:
(define (dup x)
(cons (car x) (cdr x)))
在第一个代码段中,您使用(d'(())
,它最终将一个文本绑定到d
。然后修改通常未定义的文本。在第二个代码段中,您使用(d(cons null))
将d
绑定到新创建的“cons单元格”,然后对其进行修改。修改这一点没有问题
注意:您尚未定义null
。也许您的意思是“()?在您的第一个代码段中,您使用了(d'(())
,它最终将一个文本绑定到d
。然后修改通常未定义的文本。在第二个代码段中,您使用(d(cons null))
将d
绑定到新创建的“cons单元格”,然后对其进行修改。修改这一点没有问题
注意:您尚未定义null
。也许您的意思是“()?在第一个实现中,d
的值是文字数据,并且被修改后会产生未定义的结果。要强调发生的事情,请考虑下面的代码:
(define (incorrect-list-null-and-x x)
(let ((l '(()))) ; a list of the form (() . ())
(set-cdr! l (cons x (cdr l))) ; (cdr l) is (), so (cons x (cdr l)) should be (x . ()) == (x), right?
; and now l should be (() . (x . ())) == (() x), right?
l))
预期的结果是(不正确的-list-null-and-x n)
应该返回一个形式为(()n)
的列表,并且它是第一次返回,但连续调用仍在访问相同的数据:
同样的问题在您的dup2
中表现得有点不同。从dup2
返回的每个值实际上都是同一对:
产出:
(3 . 4)(3 . 4)
因为调用(dup2(cons 3 4))
修改了先前由(dup2(cons 1 2))
返回的相同结构,所以第一个实现中d
的值是文本数据,并且修改后的结果未定义。要强调发生的事情,请考虑下面的代码:
(define (incorrect-list-null-and-x x)
(let ((l '(()))) ; a list of the form (() . ())
(set-cdr! l (cons x (cdr l))) ; (cdr l) is (), so (cons x (cdr l)) should be (x . ()) == (x), right?
; and now l should be (() . (x . ())) == (() x), right?
l))
预期的结果是(不正确的-list-null-and-x n)
应该返回一个形式为(()n)
的列表,并且它是第一次返回,但连续调用仍在访问相同的数据:
同样的问题在您的dup2
中表现得有点不同。从dup2
返回的每个值实际上都是同一对:
产出:
(3 . 4)(3 . 4)
因为调用(dup2(cons 3 4))
修改了先前由(dup2(cons 1 2))返回的相同结构
null在scheme中被定义为“()”,编辑:仅在某些实现中更正感谢(define null'null)
不是一个好的假设。OP显然打算(())
与(cons null null)
@DanielV在某些实现中是相等的。在Scheme标准中没有定义它。在Scheme中null定义为“()编辑:仅在某些实现中更正,这要感谢(定义null'null)
不是一个好的假设。OP显然打算(())
与(cons null null)
@DanielV在某些实现中是相等的。方案标准中未定义。可能重复。问题在于引用的数据,而不是'(())
和(cons null null)
的值存在差异。尝试将(())
替换为(list'())
,您将不再观察到此问题。(重复不是Scheme,而是Common Lisp,但问题是相同的。)为了获得更多乐趣,与其做一个dup
过程,不如尝试编写一个将数据推入列表d
,您会看到列表在多次调用中变得越来越长。的可能重复。问题在于引用的数据,而不是'(())
和(cons null null)
的值存在差异。尝试将(())
替换为(list'())
,您将不再观察到此问题。(这个重复不是Scheme,而是Common Lisp,但问题是相同的。)为了获得更多的乐趣,与其做一个dup
过程,不如尝试编写一个将数据推送到列表d
中的过程,您会看到列表在多次调用中越来越长。