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.
CASE Syntax: CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 WHEN condition3 THEN result3 ELSE result END; ORDER BY: This keyword is used to sort the result-set in ascending or descending order. It sorts the records in ascending order by default.
The case statement in SQL returns a value on a specified condition. We can use a Case statement in select queries along with Where, Order By, and Group By clause. It can be used in the Insert statement as well.
CASE can be used in any statement or clause that allows a valid expression. For example, you can use CASE in statements such as SELECT, UPDATE, DELETE and SET, and in clauses such as select_list, IN, WHERE, ORDER BY, and HAVING.
Which of the following is correct syntax for CASE statement? Explanation: The CASE statement is started with the keyword CASE followed by any identifier or expression and the IS.
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 to
(defun testcaseexpr (thecase)
(case thecase
((quote foo) (format t "matched foo"))
(bar (format t "matched bar"))
((funk) (format t "matched funky"))))
wherein 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. In the documentation for case
, we read that in an normal-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 have
(case operator
((and or) ...)
((if iff) ...)
((not) ...))
It makes it harder to mess up the special cases of t
and otherwise
. The documentation says about keys that (emphasis added):
keys—a designator for a list of objects. In the case of case, the symbols
t
andotherwise
may not be used as the keys designator. To refer to these symbols by themselves as keys, the designators(t)
and(otherwise)
, respectively, must be used instead.
In practice, some implementations will let you use t
and otherwise
as keys in normal-clauses, even though it seems like this shouldn't be allowed. E.g., in SBCL:
CL-USER> (macroexpand-1 '(case keyform
(otherwise 'a)
(otherwise 'b)))
(LET ((#:G962 KEYFORM))
(DECLARE (IGNORABLE #:G962))
(COND ((EQL #:G962 'OTHERWISE) NIL 'A)
(T NIL 'B)))
Using explicit lists removes any ambiguity about what you're trying to do. Even though t
and otherwise
are called out specifically, keys is a list designator, which means that nil
(an atom and a list) needs some special consideration. Will the following code produce a
or b
? (Can you tell without testing it or checking the spec? This case is actually highlighted in the examples.)
(case nil
(nil 'a)
(otherwise 'b))
It returns b
. To return a
, the first normal-clause would have to be ((nil) 'a)
.
If you always make sure that keys is a list, you'll:
case
); andIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With