Why can't CASE be used on string values and only symbol values?
Asked Answered
B

3

6

In book 'land of lisp' I read

Because the case command uses eq for comparisons, it is usually used only for branching on symbol values. It cannot be used to branch on string values, among other things.

Please explain why?

Bucella answered 18/9, 2013 at 17:40 Comment(2)
Additional hint: there are other case-like constructs in the library alexandria, including such that can compare strings.Varanasi
Because a string is like a list of characters. Only way to compare two strings that are not eq is to check if all the parts are eql. Case works with symbols, numbers and characters since they are primitive values.Tripper
L
13

The other two excellent answers do answer the question asked. I will try to answer the natural next question - why does case use eql?

The reason is actually the same as in C (where the corresponding switch statement uses numeric comparison): the case forms in Lisp are usually compiled to something like goto, so (case x (1 ...) (2 ...) (3 ...)) is much more efficient than the corresponding cond. This is often accomplished by compiling case to a hash table lookup which maps the value being compared to the clause directly.

That said, the next question would be - why not have a case variant with equal hash table clause lookup instead of eql? Well, this is not in the ANSI standard, but implementations can provide such extensions, e.g., ext:fcase in CLISP.

See also why eql is the default comparison.

Lacrosse answered 18/9, 2013 at 19:21 Comment(0)
I
11

Two strings with the same content "foo" and "foo" are not EQL. CASE uses EQL as a comparison (not EQ as in your question). Usually one might want different tests: string comparison case and case insensitive, for example. But for CASE on cannot use another test. EQL is built-in. EQL compares for pointer equality, numbers and characters. But not string contents. You can test if two strings are the identical data objects, though.

So, two strings "FOO" and "FOO" are usually two different objects.

But two symbols FOO and FOO are usually really the same object. That's a basic feature of Lisp. Thus they are EQL and CASE can be used to compare them.

Initiatory answered 18/9, 2013 at 17:53 Comment(0)
W
5

Because (eq "foo" "foo") is not necessarily true. Each time you type a string literal, it may create a fresh, unique string. So when CASE is comparing the value with the literals in the cases with EQ, they won't match.

Wilbourn answered 18/9, 2013 at 17:51 Comment(2)
This isn't entirely true; the compiler could merge the two constants in compiled system, and (eq "foo" "foo") could be true. You're right, of course, that there's no guarantee that (eq "foo" "foo") is true. "(eq "Foo" "Foo") => true OR=> false" is even one of the examples in the hyperspec entry on eq.Faxun
@JoshuaTaylor I've added qualifiers to my answer.Wilbourn

© 2022 - 2024 — McMap. All rights reserved.