6

在《口齿不清的土地》一书中,我读到

因为 case 命令使用 eq 进行比较,所以它通常只用于符号值的分支。除其他外,它不能用于在字符串值上进行分支。

请解释为什么?

4

3 回答 3

13

其他两个出色的答案确实回答了所提出的问题。我将尝试回答自然的下一个问题——为什么case使用eql

原因其实和 in 一样C(对应的switch语句使用数值比较):caseLisp 中的表单通常编译成类似的形式goto,因此(case x (1 ...) (2 ...) (3 ...))比对应的cond. 这通常通过编译case到哈希表查找来完成,该查找将要比较的值直接映射到子句。

也就是说,下一个问题是 - 为什么不使用带有哈希表子句查找的case变体而不是? 嗯,这不在 ANSI 标准中,但实现可以提供这样的扩展,例如,在 CLISP 中。equaleqlext:fcase

另请参阅为什么eql是默认比较

于 2013-09-18T19:21:39.883 回答
10

具有相同内容“foo”和“foo”的两个字符串不是 EQL。CASE用作EQL比较(不是EQ您的问题)。通常可能需要不同的测试:例如,字符串比较大小写和不区分大小写。但是对于CASEon 不能使用另一个测试。EQL是内置的。EQL比较指针相等、数字和字符。但不是字符串内容。不过,您可以测试两个字符串是否是相同的数据对象。

"FOO"所以,两个字符串"FOO"通常是两个不同的对象。

但是两个符号FOOFOO通常实际上是同一个对象。这是 Lisp 的一个基本特性。因此,它们是EQL并且CASE可以用来比较它们。

于 2013-09-18T17:53:40.363 回答
5

因为(eq "foo" "foo")不一定是真的。每次键入字符串文字时,它可能会创建一个新的、唯一的字符串。因此,当CASE将值与带有 的情况下的文字进行比较时EQ,它们将不匹配。

于 2013-09-18T17:51:47.433 回答