在下面的case语句中,x被设置为#\ j,但是返回了“bye”。
(case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))
find应该返回#\ j,它应该匹配x,对吗?
答案 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 的重点:键是常量的,因此可以编译表单以生成更高效的代码。如果你想要动态密钥,那么使用关联列表,哈希表等