Lists are not atoms, that's the important part here. Symbols though are atoms, that means that when they are the same, they reside in the same memory, they are like numbers and can indeed be seen as pointers. Symbols are not mutable too, a symbol foo
is like a number 3
.
Lists however are not atoms, two lists, or strings, of vectors with the same contents can very well reside into two different places of memory.
eq?
tests on memory location only. eqv?
tests in equivalence, what that is is vague and it depends on which implementation, the Scheme standard is fairly liberal with this, it only says that it must at least be a superset of eq?
basically. equal?
on the other end tests on structural equality and does so recursively, so it's a very expensive operation and that's why symbols are often preferred to strings for identifiers.
(define l1 (list 1 2 3))
(define l2 (list 1 2 3))
(eq? l1 l2) ; ===> #f in most implementations
(equal? l1 l2) ; ===> #t in all implementations
(eqv? l1 l2) ; ===> #t in some implementations
(define l3 (cdr l1))
(define l4 (cdr l1))
(eq? l3 l4) ; ===> #t, this means that they 'share memory', if you change l3 or l4, l1 will change with it, beware. This is how car and cdr work, they do not copy.
(define l6 (cons 1 l4));
(eq? l1 l6) ; ===> #f again, cons does allocate new memory, but the tails may very well share it, s in this case, l6 does share its tail with all lists except l2 here in memory.
Also, a bit of terminology, cons creates a pair, this is different from a list of two elements, it creates a pair (a . b)
the list (a b)
is in fact identical to the pair (a . (b . ()))
Also, cons and car and cdr are primitives, the implementation you see below is the demonstration in Structure and Implementation of Computer Programs that shows they aren't strictly needed as them, but having them as primitives dramatically increases performance, so better not re-define your cons, car and cdrs.