Defparameter и предикат равенства, используемый в случае макроса - PullRequest
4 голосов
/ 22 июня 2019

У меня есть несколько глобальных переменных типа integer, созданных с помощью defparameter.Я использую их в качестве ключей в предложениях CASE для сопоставления с test-key, который в какой-то момент в моей программе был установлен на одну из этих глобальных переменных.

Насколько я знаю, макрос CASE использует EQL (http://clhs.lisp.se/Body/26_glo_s.htm#same), но я не получаю совпадения: все помещено в предложение иначе. Код ниже суммирует то, что меня озадачивает.

  • (defparameter snafu 123) => SNAFU
  • (let ((x snafu)) (и (eq x snafu) (eql x snafu) (равно x snafu))) => T
  • (let ((x snafu))) (случай x(snafu 'yes) (t' no))) => NO
  • (let ((x snafu)) (cond ((eql x snafu) 'yes) (t' no))) => YES

Я не понимаю, почему я не получаю ДА в случае.

Ответы [ 3 ]

5 голосов
/ 22 июня 2019

Кейсы не оцениваются, они воспринимаются буквально.Это:

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

эквивалентно:

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

Обратите внимание на то, что перед snafu: x сравнивается символ snafu, а не его значение.

2 голосов
/ 23 июня 2019

Поскольку case является макросом, можно узнать, какой код он генерирует:

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

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

Можно видеть, что snafu используется как буквенный символ, а не как переменная.

1 голос
/ 22 июня 2019

Я начал работать над этим, прежде чем увидел ответ @ coredump.Вот еще один пример:

(progn (defparameter snafu 'y) 
       (let ((x snafu)) 
           (case snafu (y 'case-keys-are-constants))))

; => CASE-KEYS-ARE-CONSTANTS

...