Switch statement in Lisp
Asked Answered
M

3

6

Switch statement with Strings in Lisp.

    (defun switch(value) 
      (case value
        (("XY") (print "XY"))
        (("AB") (print "AB"))
      )
    ) 

I want to compare if value is "XY" then print "XY" or same for "AB". I have tried this code but it gives me nil. Can some please tell me what i am doing wrong?

Motivity answered 1/3, 2016 at 14:48 Comment(3)
Your parentheses are all wrong, and case compares by identity.Alane
@Alane can you please point out the mistakes. Because i am completely lost with this 'case'. I tried bunch of changes but none of them worked for meMotivity
print("XY") ? Which programming language is that? Does it look like Lisp? Not really.Dwan
M
9

print("XY") looks more like Algol (and all of its descendants) rather than LISP. To apply print one would surround the operator and arguments in parentheses like (print "XY")

case happens to be a macro and you can test the result yourself with passing the quoted code to macroexpand and in my implementation I get:

(let ((value value)) 
  (cond ((eql value '"XY") (print "XY")) 
        ((eql value '"AB") (print "AB"))))

You should know that eql is only good for primiitive data types and numbers. Strings are sequences and thus (eql "XY" "XY") ;==> nil

Perhaps you should use something else than case. eg. use cond or if with equal.

Mckeon answered 1/3, 2016 at 16:11 Comment(0)
A
10

You can use the library alexandria, which has a configurable switch macro:

(switch ("XY" :test 'equal)
  ("XY" "an X and a Y")
  ("AB" "an A and a B"))
Antipathetic answered 1/3, 2016 at 17:47 Comment(0)
M
9

print("XY") looks more like Algol (and all of its descendants) rather than LISP. To apply print one would surround the operator and arguments in parentheses like (print "XY")

case happens to be a macro and you can test the result yourself with passing the quoted code to macroexpand and in my implementation I get:

(let ((value value)) 
  (cond ((eql value '"XY") (print "XY")) 
        ((eql value '"AB") (print "AB"))))

You should know that eql is only good for primiitive data types and numbers. Strings are sequences and thus (eql "XY" "XY") ;==> nil

Perhaps you should use something else than case. eg. use cond or if with equal.

Mckeon answered 1/3, 2016 at 16:11 Comment(0)
S
4

The Hyperspec on CASE says:

These macros allow the conditional execution of a body of forms in a clause that is selected by matching the test-key on the basis of its identity.

And strings are not identical in CL, i.e. (EQ "AB" "AB") => NIL.

That is why CASE wouldn't work for strings. You either need to use symbols (they are interned once only, thus guaranteeing identity) or use COND with EQUAL or even EQUALP if the letters case to be ignored.

Stallion answered 2/3, 2016 at 8:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.