I am confused about the difference between '(()) and (cons null null) in scheme.
The code below show that b
and c
are completely the same thing.
(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)
However, when I used dup
instead of 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)
Variable b
and c
are different. I have done some experiments, but I haven't understand yet.
Data literals, like
'(())
, are meant to be read-only, and modifying it usingset-car!
orset-cdr!
has undefined behaviour. For predictable behaviour, use the(cons '() '())
version if you want to useset-car!
orset-cdr!
on it.In particular,
cons
creates a new cons cell, whereas a data literal usually won't.Still, for the purposes of implementing
dup
, why are you usingset-car!
andset-cdr!
anyway? Just usecons
directly:In your first code snippet you use
(d '(()))
which ends up binding a literal tod
. You then modify the literal which is generally undefined. In your second code snippet you use(d (cons null null))
which bindsd
to a newly created 'cons cell' which you then modify. There is no problem modifying that.Note: you've not defined
null
. Perhaps you meant '()?The value of
d
in the first implementation is literal data, and is modified with undefined consequences. To highlight what's happening, consider the following code:The expected result is that
(incorrect-list-null-and-x n)
should return a list of the form(() n)
, and it does the first time, but successive calls are still accessing the same data:The same problem manifests itself a bit differently in your
dup2
. Every value returned fromdup2
is actually the same pair:outputs:
because the call
(dup2 (cons 3 4))
modifies the same structure that was previously returned by(dup2 (cons 1 2))
.