0

Can you explain why the first one is false and the second one is true?

And how this works? Thanks.

(eq? '(1 2 3) '(1 2 3)) ;False
(eq? '() '()) ;True
Honolulu
  • 23
  • 3
  • It may interest you to know that the standard explicitly says that `(eq? '() '())` must be `#t`. See: https://schemers.org/Documents/Standards/R5RS/HTML/ – Flux Feb 22 '20 at 05:33
  • The result of `(eq? '(1 2 3) '(1 2 3))` can be any of `#t` or `#f` depending on the implementation reuses literals or not. This the statement that it is false is not always true. – Sylwester Feb 22 '20 at 18:27

2 Answers2

2

There's only one empty list, so all uses of () refer to that list, and it's eq? to itself. The Scheme Specification description of the storage model says:

Notwithstanding this, it is understood that the empty list cannot be newly allocated, because it is a unique object.

and the specification of eqv? (which is referenced by the eq? description) says that two objects are equivalent if

obj1 and obj2 are both the empty list

But when you create a non-empty list, it creates a fresh one every time, and they're not eq? to each other even if they contain the same elements.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • actually `'()` is associated with a symbol, which is unique for all empty lists.... so it has a unique address. – alinsoar Feb 22 '20 at 12:22
  • @alinsoar In Lisp it's the symbol `NIL`. I don't think that's true in Scheme. – Barmar Feb 22 '20 at 14:16
  • I think it's like an internal symbol, not an interned symbol in the obarray where are stored the user-visible symbols. – alinsoar Feb 22 '20 at 14:20
  • @alinsoar R7RS says "The empty list is a special object of its own type." – Barmar Feb 22 '20 at 14:43
  • I know you are right and I do not want to be in contradiction with you. My statement was like a question: <> -- such that no symbol created by user will ever fall at the same address as the symbol associated for '()... – alinsoar Feb 22 '20 at 16:28
  • 1
    You can think of it however you like, but it's best to just think of it as a special object used just for this purpose. Scheme deliberately avoided conflating the empty list with a symbol like Lisp does; Lisp's NIL is heavily overloaded. – Barmar Feb 22 '20 at 16:41
  • Actually the implementation can reuse literal data so the same quoted data in different locations might be reused making the `(eq? '(1 2 3) '(1 2 3)) ; ==> #t`. This is the reason mutating literal data is not Scheme and thus anything could happen. Most implementation ends up mutating all the reused places where in Racket you get an error. – Sylwester Feb 23 '20 at 01:06
2

Quoted from TSPL3:

[..] Two objects are considered identical if they are represented internally by the same pointer value [..] The empty list () is identical to itself wherever it appears. [..] Two pairs, vectors, or strings created by different applications of cons, vector, string, etc., are distinct.

If you write instead

(let ((x '(1 2 3)))
  (eq? x x))

it will be #t.

vukung
  • 1,824
  • 10
  • 23
  • TSPL is not the official place to look for language specifications. the [RNRS reports](https://schemers.org/Documents/Standards/) are. The result of (eq? '(1 2 3) '(1 2 3)) can be any of `#t` or `#f` and still be in line with RNRS specs. – Sylwester Feb 25 '20 at 13:03