3

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.

Alex Pritchard
  • 4,260
  • 5
  • 33
  • 48
  • That's strange. I just tried your first case expression in GNU Common Lisp 2.6.7 and (as expected) it evaluates to B. – August Karlstrom May 23 '11 at 14:00
  • 4
    "xlisp" is an important bit of information, from the [web page](http://www.xlisp.org/): "XLISP 3.0 is a superset of the **Scheme** dialect of Lisp" – Eli Barzilay May 23 '11 at 14:34

5 Answers5

4

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
WReach
  • 18,098
  • 3
  • 49
  • 93
2

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))
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
1

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
Erhan Bagdemir
  • 5,231
  • 6
  • 34
  • 40
1

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.

lindelof
  • 34,556
  • 31
  • 99
  • 140
0

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))
Eli Barzilay
  • 29,301
  • 3
  • 67
  • 110