Reputation: 135
there has to be a better way to do this here, right?
(format t "Enter your age: ~%")
(defun age-case (age)
(case age
(1 (format t "You belong in Kindergarden~%"))
(2 (format t "You belong in Kindergarden~%"))
(3 (format t "You belong in Kindergarden~%"))
(4 (format t "You belong in Kindergarden~%"))
(5 (format t "You belong in Preschool~%"))
(6 (format t "Elementary school ~%"))
(t (format t "Somewhere else"))))
(defvar *age* (read))
(age-case *age*)
In Python I would use a case 1..4 for this, in C++, Java and co. I would maybe use a falltrough switch case where I leave out the break for cases 1 to 3. Is there a neat little trick to do this in clisp w/o the code duplication?
Upvotes: 2
Views: 217
Reputation: 557
A case
clause can accept multiple keys:
(defun age-case (age)
(case age
((1 2 3 4) (format t "You belong in Kindergarden~%"))
(5 (format t "You belong in Preschool~%"))
(6 (format t "Elementary school ~%"))
(t (format t "Somewhere else"))))
Rainer's solution used ranges provided in the integer
type with a typecase
:
(typecase age
((integer 1 4) 'one-to-four)
((eql 5) 'five)
((eql 6) 'six)
(t 'something-else)))
Building on this, you can do type checking "for free":
(etypecase age
((integer 1 4) 'one-to-four)
((eql 5) 'five)
((eql 6) 'six)
((integer 7 *) 'something-else)))
Alternatively, you can also use cond
:
(cond
((<= 1 age 100) 'one-to-ahundred)
;; ...and so on.
)
Upvotes: 5
Reputation: 139251
Another option is to use type specifiers:
CL-USER > (let ((age 6))
(typecase age
((integer 1 4) 'one-to-four) ; integers from 1 to 4
((eql 5) 'five)
((eql 6) 'six)
(t 'something-else)))
SIX
Upvotes: 7
Reputation: 7568
You can use cond and member like this:
(defun age-test ()
(format t "Enter your age: ~%")
(finish-output)
(let ((age (read)))
(format t (cond ((member age '(1 2 3 4)) "You belong in Kindergarden~%")
((= age 5) "You belong in Preschool~%")
((= age 6) "Elementary school ~%")
(t "Somewhere else")))))
(age-test)
Upvotes: 1