These all work:
(defun testcaseexpr (thecase)
(case thecase
('foo (format t "matched foo"))
(bar (format t "matched bar"))
((funk) (format t "matched funky"))))
Which of these three expressions is considered the idiomatic way? And perhaps as a side point, why are they all working, when clearly they are not the same syntax. In fact in other contexts they have different semantics completely. A list (funk)
is certainly not the same as a quoted atom, 'foo
. Yet just passing in the words foo
bar
and funk
all work the same.
Second :)
First is never used, unless you expand a macro into something like it by accident, and third is used when you have more then one matching symbol (a fall-through case).
First, note that you've actually only got two cases here.
'foo
is expanded by the reader as(quote foo)
, so your code is equivalent towherein the first and third cases have the same structure; the keys part of the clause is a list of objects.
Perhaps this question is off-topic, since it's asking for the “best”, and that might be primarily opinion based. I agree with the points made in wvxvw's answer, but I tend to use the style you've shown in the third case almost exclusively. I've got a couple reasons for this:
It's the most general form.
It's the most general form. In the documentation for
case
, we read that in annormal-clause ::= (keys form*)
keys
is a designator for a list of keys. This means that a clause like(2 (print 'two))
is equivalent to((2) (print 'two))
. You never lose anything by using a list instead of a non-list, but if you have some clauses with multiple objects and some with single objects, you'll have consistent syntax for all of them. E.g., you can haveIt's harder to mess up.
It makes it harder to mess up the special cases of
t
andotherwise
. The documentation says about keys that (emphasis added):In practice, some implementations will let you use
t
andotherwise
as keys in normal-clauses, even though it seems like this shouldn't be allowed. E.g., in SBCL:Using explicit lists removes any ambiguity about what you're trying to do. Even though
t
andotherwise
are called out specifically, keys is a list designator, which means thatnil
(an atom and a list) needs some special consideration. Will the following code producea
orb
? (Can you tell without testing it or checking the spec? This case is actually highlighted in the examples.)It returns
b
. To returna
, the first normal-clause would have to be((nil) 'a)
.Conclusion
If you always make sure that keys is a list, you'll:
case
); and