在下面的 case 语句中,x 被设置为 #\j,但返回了 "bye"。
(case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))
find 应该返回 #\j,它应该匹配 x,对吗?
在下面的 case 语句中,x 被设置为 #\j,但返回了 "bye"。
(case (find #\j "joy") ((x) (princ "hi")) (otherwise (princ "bye")))
find 应该返回 #\j,它应该匹配 x,对吗?
我们来看一下。
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"
不评估子句键,因此子句((x)...)
将仅匹配符号x
。这就是case的重点:键是常量,因此可以编译表单以生成更高效的代码。如果您想要动态键,请使用关联列表、哈希表等。