Thanks for releasing this library. I've written quite a few large 
command-line driven applications in Clojure thus far, and each one has used 
a slightly different homegrown approach as different core functionality 
became available (and the contrib libs kept mutating). Your state monad 
inspired approach definitely clicks with me, and I'll be looking forward to 
your future releases.

Also, I agree with Stathis that there is a problem including the errors map 
in the original data structure under an unqualified keyword. Of course, if 
you change validate to not modify the input map that is being validated, 
then you no longer need a state monad to model the validation workflow. 
This could just as easily be done with a simple reduce. In this instance, 
I'd guess that just qualifying the ::errors keyword would probably stick 
closest to your original model. Maybe I'm totally missing the mark here 
though.

Additionally, one thing that bit me when using validate with multiple tests 
was that there's no early exit strategy. For example, imagine I have 
written a test like the following:

(def config-params {:input-dir "some/directory/path" :output-dir 
"some/other/directory/path"})

(defvalidator directory
  {:default-message-format "%s must be a valid directory" :optional false}
  [path]
  (.isDirectory ^File (clojure.java.io/file path)))

(defvalidator readable
  {:default-message-format "%s is not readable" :optional false}
  [path]
  (.canRead ^File (clojure.java.io/file path)))

(defvalidator writeable
  {:default-message-format "%s is not writeable" :optional false}
  [path]
  (.canRead ^File (clojure.java.io/file path)))

(validate config-params
  :input-dir [required directory readable]
  :output-dir [required directory writeable])

The problem that I run into is that if for some reason :input-dir or 
:output-dir are not defined in config-params, then I get a 
NullPointException when .isDirectory is called in the directory validator. 
I can, of course, dodge this bullet by setting :optional true in the 
directory, readable, and writeable validators. However, as evidenced by the 
required validator's presence in my test vectors, I actually do want these 
fields to be present and to pass all tests. So the semantics sort of look a 
bit off to me in this instance.

Another case that perhaps illustrates my point a little more clearly is 
this one:

(defvalidator <10 {:default-message-format "%s must be less than 10" 
:optional false} [x] (< x 10))

(validate {:foo "I'm a string, but I should be a number"}
  :foo [required number <10])

Here, I obviously get this exception: ClassCastException java.lang.String 
cannot be cast to java.lang.Number  clojure.lang.Numbers.lt

Again, my problem is that since number fails, I would like <10 to never be 
called. The :optional flag can't help me here because it only disables 
validators in the case of a nil input.

So basically what I'm suggesting as an enhancement to your library is that 
whenever a field is being tested with a multi-validator vector, the first 
test to fail should prevent any other tests (to its right in the vector) 
from running. This would be similar in spirit to the behavior of the -?> 
and -?>> thread-maybe macros in clojure.core.incubator.

Okay, constructive criticism and all that aside, great work on this library 
again. Looking forward to the next release soon.

  ~Gary

On Wednesday, January 9, 2013 4:24:14 PM UTC-5, Leonardo Borges wrote:
>
> Stathis, 
>
> That's a very good point. I've been thinking about the usefulness of 
> returning the errors map in the original map since the errors map itself is 
> returned as the first element in the call to 'validate'. 
>
> To be honest I'm tempted to remove that with the next release, making 
> validate return a single value: the errors map. 
>
> I'm happy for you to argue otherwise though. Do you think having the 
> qualified keywords in the original map is still useful? 
>
> I'll be releasing a new version over the weekend that will include this 
> change. 
>
> Thanks for the feedback
>
> Leonardo Borges
> www.leonardoborges.com
> On Jan 10, 2013 7:08 AM, "Stathis Sideris" <sid...@gmail.com <javascript:>> 
> wrote:
>
>> Hey Leonardo,
>>
>> This is very interesting, but I'd like to know whether it's possible to 
>> validate a map that contains an :errors key. Would bouncer overwrite this 
>> with its own :errors key? Should it not be using a fully-qualified keyword 
>> (as in ::errors) to avoid the clash?
>>
>> Thanks,
>>
>> Stathis
>>
>>
>> On Friday, 4 January 2013 06:56:19 UTC, Leonardo Borges wrote:
>>>
>>> Hey guys, 
>>>
>>> I extracted a small validation library from a side project I'm working 
>>> on and bouncer is the result. 
>>>
>>> While I do know there are a couple of validation libs out there 
>>> already, I decided this was worth publishing mostly because: 
>>>
>>> - That’s what I’m using in my current side project 
>>> - It takes a fundamentally different implementation approach that is 
>>> in itself worthy of exploration 
>>> - If nothing else, this is yet another example of where Monads can be 
>>> useful. 
>>>
>>> The full reasoning can be found in a post I wrote: 
>>> https://bitly.com/ZiLJzO 
>>>
>>> Where to find it: 
>>>
>>> Github: 
>>> https://github.com/**leonardoborges/bouncer<https://github.com/leonardoborges/bouncer>
>>>  
>>> Clojars: https://clojars.org/bouncer 
>>>
>>> The README file on github contains a detailed guide to using the 
>>> library, hopefully that's enough should you want to try it out. 
>>>
>>> Cheers, 
>>> Leonardo Borges 
>>> www.leonardoborges.com 
>>>
>>  -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com<javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>
>

-- 
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