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

Reply via email to