在case宏中使用的参数和相等谓词

时间:2019-06-22 18:40:47

标签: common-lisp

我使用defparameter创建了一些整数类型的全局变量。我将它们用作CASE子句中的键,以匹配在程序中的某个时刻设置为这些全局变量之一的test-key。

据我所知,CASE宏使用EQL(http://clhs.lisp.se/Body/26_glo_s.htm#same),但我没有找到匹配项:所有内容都被转储到else子句中。下面的代码总结了让我感到困惑的地方。

  • (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)))=>否
  • (让(((x snafu))(cond((eql x snafu)'yes)(t'no)))=>是

我不明白为什么我在案例中没有得到同意。

3 个答案:

答案 0 :(得分:5)

不对case子句求值,它们按字面意义使用。 这个:

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

等效于:

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

请注意,将snafu前的引号:x与符号snafu而不是其值进行比较。

答案 1 :(得分:2)

由于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被用作文字符号,而不是变量。

答案 2 :(得分:1)

在看到@coredump的答案之前,我开始进行此工作。这是另一个示例:

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

; => CASE-KEYS-ARE-CONSTANTS