Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defparameter and equality predicate used in case macro

Tags:

common-lisp

I have some global variables of type integer created with defparameter. I use these as keys in CASE clauses to match at test-key that was, at some point in my program, set to one of these global variables.

So far as I know, the CASE macro uses EQL (http://clhs.lisp.se/Body/26_glo_s.htm#same), but I don't get a match: all is dumped into the otherwise clause. Code below summarises what's puzzling me.

  • (defparameter snafu 123) => SNAFU
  • (let ((x snafu)) (and (eq x snafu) (eql x snafu) (equal x snafu))) => T
  • (let ((x snafu)) (case x (snafu 'yes) (t 'no))) => NO
  • (let ((x snafu)) (cond ((eql x snafu) 'yes) (t 'no))) => YES

I don't understand why I don't get YES in the CASE.

like image 218
peter.cntr Avatar asked Jan 26 '23 04:01

peter.cntr


2 Answers

Case clauses are not evaluated, they are taken literally. This:

(case x
  (snafu 'yes)
  (t 'no))

is equivalent to:

(if (eql x 'snafu) 'yes 'no)

Note the quote before snafu: x is compared against the symbol snafu and not its value.

like image 97
coredump Avatar answered Feb 03 '23 12:02

coredump


Since case is a macro, one can find out what code it generates:

* (pprint (macroexpand-1 '(case x
                            (snafu 'yes)
                            (t 'no))))

(LET ((#:G427 X))
  (DECLARE (IGNORABLE #:G427))
  (COND ((EQL #:G427 'SNAFU) NIL 'YES)
        (T NIL 'NO)))

One can see that snafu is used as a literal symbol, not a variable.

like image 33
Rainer Joswig Avatar answered Feb 03 '23 12:02

Rainer Joswig