7

GNU Emacs Lisp Reference Manual, 2.8 Equality Predicates:

Comparing circular lists may therefore cause deep recursion that leads to an error, and this may result in counterintuitive behavior such as (equal a b) returning t whereas (equal b a) signals an error.

I've found a case:

ELISP> (setq a '#1=(t .  #1#)
             b    `(t t . ,a))
ELISP> (equal b a)
t
ELISP> (equal a b)
*** Eval error ***  List contains a loop: #1=(t . #1#)
ELISP> 

Does Elisp test eq first when testing equal?
If so, I don't think (equal a b) will signal an error.

I mean,

a: t ---
   ^    |
   |    |
    ----
b: t -> t -> t ---
             ^    |  This loop is `a`.
             |    |
              ----

when testing whether a eqs b:

  1. a and b are not the same obj (i.e. not eq)
  2. so test their first element, and t eqs t; then test their CDRs
  3. a's CDR and b's CDR are not the same obj
  4. so test CDRs' first element, and t eqs t; then test CDRs' CDRs
  5. a eqs a

so I think (equal a b) should return t.

Where is my mistake?

shynur
  • 4,065
  • 1
  • 3
  • 23

1 Answers1

3

Great question!

Emacs detects the circularity of a and reports it before it descends far enough into b to discover that they are equal.

The reason for the asymmetry is that Emacs only has to check for circularity of one argument, not both.

Does Elisp test eq first when testing equal?

Yes, of course.

sds
  • 5,928
  • 20
  • 39