在书籍'lisp之乡'中我读了
因为case命令使用eq进行比较,所以通常使用它 仅用于符号值的分支。它不能用于分支 字符串值,等等。
请解释原因?
答案 0 :(得分:13)
另外两个优秀的答案确实回答了问题。我会尝试回答下一个自然的问题 - 为什么case
使用eql
?
原因实际上与C
中相同(其中相应的switch
语句使用数字比较):Lisp中的case
表单通常编译为{{1} },因此goto
比相应的cond
更有效。这通常是通过将(case x (1 ...) (2 ...) (3 ...))
编译为哈希表查找来实现的,哈希表查找将直接比较的值映射到子句。
那就是说,下一个问题是 - 为什么没有case
变体与case
哈希表子句查找而不是equal
?嗯,这不是ANSI标准,但实现可以提供这样的扩展,例如CLISP中的ext:fcase
。
答案 1 :(得分:10)
具有相同内容“foo”和“foo”的两个字符串不是EQL。 CASE
使用EQL
作为比较(不是EQ
,如您的问题)。通常,人们可能需要不同的测试:例如,字符串比较大小写和不区分大小写。但是对于CASE
on不能使用另一个测试。 EQL
是内置的。 EQL
比较指针相等,数字和字符。但不是字符串内容。但是,您可以测试两个字符串是否是相同的数据对象。
因此,两个字符串"FOO"
和"FOO"
通常是两个不同的对象。
但是两个符号FOO
和FOO
通常是同一个对象。这是Lisp的基本功能。因此,它们EQL
和CASE
可用于比较它们。
答案 2 :(得分:5)
因为(eq "foo" "foo")
不一定是真的。每次键入字符串文字时,它都可以创建一个新的唯一字符串。因此,当CASE
将值与EQ
案例中的文字进行比较时,它们将不匹配。