Reputation: 1928
I'm writing a simple DiceRoller application and I've created the primary function, however I'm wondering if there is a "smart" way to validate function inputs in Clojure rather than using branching conditionals to validate input? My function is below with a sample test, I would have to also test if n is not a number with another if or an or and it feels messy.
Also if anyone can point out a smarter way to do this function I would appreciate any feedback, this is my first attempt at trying to program functionally
(ns DiceRoller)
(defn roll
"rolls a specified number of n sided dice "
([] (roll 1 6))
([number] (roll number 6))
([number n]
(if-not number? number (throw (IllegalArgumentException. (str "incorrect input, integers only"))))
(take number (repeatedly #(+ (rand-int n) 1)))
)
)
Upvotes: 10
Views: 2303
Reputation: 56665
Sure there is - you can use a :pre
assertion for that.
(defn some-fun [x]
{:pre [(number? x)]}
(foo x))
Now you'll get AssertionError Assert failed: (number? x) if you pass the function a non-numeric argument x
.
Checking whether the input is a number is kind of useless as @amalloy already pointed out, but there are lots of totally valid precondition (and postcondition for that matter) checks that you might want to apply to your function. You can see some more details on the subject here and here.
Upvotes: 25
Reputation: 92117
Mostly the Clojure attitude is "just assume you got the right thing". In this case, if you took out your check entirely, the user would get basically the same exception eventually. But if you really wanted to do this, you should do it correctly! Right now your code throws an exception on every input, because you're missing parens around (number? number)
.
Upvotes: 7