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?

0

1 Answer 1

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.

1
  • @Shynur: Let's remove the comments - their gist is now in the answer.
    – sds
    Jan 13, 2023 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.