Reputation: 4250
I'm trying to use a case statement to make some code more readable. It seems to work as a series of if statements, but for some reason the case statement always accepts a comparison to nil even if it is not true. Can someone clarify why this behavior occurs?
Example:
> (case 'a
(nil nil)
(otherwise 'b))
NIL
> (case 'a
('a 'b)
(otherwise nil))
B
In the above example, the first instance returns nil, even though 'a clearly is not nil. Trying to do the same thing with if statements behaves as I would expect:
> (if (eq 'a nil) nil 'b)
B
> (if (eq 'a 'a) 'b nil)
B
I'm assuming there is some behavior about the case statement I do not understand. Any help would be appreciated.
Edit: Just to clarify, I know that 'a won't be evaluated. I just mocked up this example to create a situation in which the target of the case statement was definitely NOT nil.
I'm using xlisp-plus, but I'm going to try a real clisp install and see if it behaves differently.
Edit (one more time): Installed CLISP and it works fine there. Not really worth the trouble to investigate why xlisp is different. Thanks for the sanity check, everyone.
Upvotes: 3
Views: 4449
Reputation: 18271
Each of the key specifications in a CASE
may be either a list of literals or a single atom. However, CLtL says that the atom must not be NIL
since it is ambiguous as to whether it is the literal NIL
or an empty list. Use a list of NIL
instead:
> (case 'a
((nil) nil)
(otherwise 'b))
B
> (case nil
((nil) nil)
(otherwise 'b))
NIL
Upvotes: 4
Reputation: 139251
Common Lisp expects for CASE the item to test to be an atom or a list of atoms. The test also is the function EQL.
(case 'a
(a 'b) ; EQL a
(otherwise 'foo))
(case 'a
((a b c) 'foo) ; EQL to one of a, b or c
(otherwise 'bar))
The quoted for only works by accident. Don't use it:
; don't use this:
(case 'a
('a 'foo) ; <- bad! , EQL to QUOTE or A
(otherwise 'bar))
Above is the same as:
; don't use this:
(case 'a
((quote a) 'foo) ; <- bad! , EQL to QUOTE or A
(otherwise 'bar))
Upvotes: 2
Reputation: 29546
The values in a case
form are implicitly quoted lists of literals, so this:
(case 'a
((a) 'b)
(otherwise nil))
is what you want. otherwise
should work (as others have said) -- try t
instead.
BTW, when you used 'a
the reader reads it as (quote a)
which means that it will also choose it when the value is quote
, for example:
(case 'quote
('a 'b)
(otherwise nil))
Upvotes: 0
Reputation: 35240
Same here with SBCL:
CL-USER> (case 'a
(nil nil)
(otherwise 'b))
B
That said, 'a
is a symbol and as such can never be nil
.
Upvotes: 1
Reputation: 5327
i think that it depends on your LISP version. I have LispWorks on Mac and my result :
CL-USER 2 : 1 > (case 'a
(nil nil)
(otherwise 'b))
B
Upvotes: 1