On Fri, Apr 8, 2011 at 9:48 PM, James Reeves <jree...@weavejester.com> wrote: > I'm saying that if a predicate is passed a value that doesn't match a > precondition, the predicate could return a truthy value, rather than > false.
Better yet: maybe we're looking at this backwards. Maybe what we want isn't a predicate for *passed* validation, but a predicate for *failed* validation: (defn s-blank? [x] (if (empty? (.trim x)) "must not be blank")) (defn s-not-integer-or-blank? [x] (if-not (s-blank? x) (try (Integer/parseInt x) (catch Exception _ "must be an integer") nil))) (defn s-out-of-range-integer? [x lo hi] (if-not (s-blank? x) (if-not (s-not-integer? x) (let [n (Integer/parseInt x)] (if (< n lo) (str "must not be less than " lo) (if (> n hi) (str "must not be greater than " hi))))))) (defn s-not-in-range-integer? [x lo hi] (or (s-blank? x) (s-not-integer-or-blank? x) (s-out-of-range-integer? x lo hi))) (defn s-not-blank-or-in-range-integer? [x lo hi] (or (s-not-integer-or-blank? x) (s-out-of-range-integer? x lo hi))) ... (if-let [err (s-not-blank-or-in-range-integer? input 5 10)] (println "Input " err) (if-not (s-blank? input) (do-something-with input))) This takes advantage of the fact that the error messages we want are all "truthy". It's also the case that you often want to detect and handle invalid input right away, then get to the meat of the logic. The natural ordering of if, if-let, etc. puts the "true" case first. Making the "true" case the error case lets you easily get it out of the way first in your code. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en