为什么没有找到返回元素作为案例的关键?

nym*_*ymo 1 common-lisp

在以下case语句中,x被设置为#\ j,但返回"bye".

(case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))
Run Code Online (Sandbox Code Playgroud)

find应该返回#\ j,它应该匹配x,对吧?

Rai*_*wig 5

我们来看一下.

CL-USER 2 > (setf x #\j)
#\j

CL-USER 3 > (case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))
bye
"bye"
Run Code Online (Sandbox Code Playgroud)

简化:让我们摆脱它FIND.

CL-USER 4 > (case #\j ((x) (princ "hi")) (otherwise (princ "bye")))
bye
"bye"
Run Code Online (Sandbox Code Playgroud)

不行.简化:不要PRINC.

CL-USER 5 > (case #\j ((x) (princ "hi")) (otherwise "bye"))
"bye"
Run Code Online (Sandbox Code Playgroud)

不行.简化:不要PRINC.

CL-USER 6 > (case #\j ((x) "hi") (otherwise "bye"))
"bye"
Run Code Online (Sandbox Code Playgroud)

不行.我们有一个小表达.CASE是一个宏.让我们扩展表格:

CL-USER 7 > (macroexpand '(case #\j ((x) "hi") (otherwise "bye")))
(LET ((#:G1084 #\j))
  (COND ((OR (EQL (QUOTE X) #:G1084)) "hi")
        (T "bye")))
T
Run Code Online (Sandbox Code Playgroud)

哦,X是引用而不是评估.因此,您正在测试字符#\j是否等于符号X.这失败了.

CASE 不评估密钥.

解决方案:要么使用类似的东西,COND要么写一个隐藏类似的宏COND.这已被多次写成练习.

CL-USER 8 > (let ((value (find #\j "joy")))
              (cond ((eql value x) "hi")
                    (t "bye")))
"hi"
Run Code Online (Sandbox Code Playgroud)