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

时间:2013-01-11 05:33:15

标签: common-lisp

在下面的case语句中,x被设置为#\ j,但是返回了“bye”。

(case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))

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

2 个答案:

答案 0 :(得分:5)

让我们来看看。

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

CL-USER 3 > (case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))
bye
"bye"

简化:让我们摆脱FIND

CL-USER 4 > (case #\j ((x) (princ "hi")) (otherwise (princ "bye")))
bye
"bye"

不起作用。简化:不要PRINC

CL-USER 5 > (case #\j ((x) (princ "hi")) (otherwise "bye"))
"bye"

不起作用。简化:不要PRINC

CL-USER 6 > (case #\j ((x) "hi") (otherwise "bye"))
"bye"

不起作用。我们有一个小表达。 CASE是一个宏。让我们扩展表单:

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

哦,X被引用而未被评估。因此,您正在测试角色#\j是否等于符号X。这失败了。

CASE不评估密钥。

解决方案:使用COND之类的内容或编写隐藏COND之类的内容的宏。这已被多次写成练习。

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

答案 1 :(得分:3)

不评估子句键,因此子句((x)...)将匹配符号x。这就是 case 的重点:键是常量的,因此可以编译表单以生成更高效的代码。如果你想要动态密钥,那么使用关联列表,哈希表等