When function is throwing exception because of argument. I would prefer to 
throw IllegalArgumentException not AssertionError. 


(defn check [type data]
  (if (sp/valid? type data)
    true
    (throw (IllegalArgumentException. (sp/explain type data)))))


Br,
Mamun


On Friday, September 16, 2016 at 7:20:53 AM UTC+2, joakim.t...@nova.com 
wrote:
>
> I came up with this solution:
>
> (ns spec-test.core
>   (:require [clojure.spec :as s]))
>
> (s/def :user/name string?)
> (s/def :common/user (s/keys :req [:user/name]))
>
> ;; with this little helper function...
> (defn check [type data]
>   (if (s/valid? type data)
>     true
>     (throw (AssertionError. (s/explain type data)))))
>
> ;; I can use it in my :pre condition
> (defn aname [user]
>   {:pre [(check :common/user user)]}
>   (-> user :user/name))
>
> ;; when I call name with an illegal arguement...
> (aname {:x "Elon"})
>
> ;; ...it not fails and returns a better error message:
> CompilerException java.lang.AssertionError: null, 
> compiling:(/Users/joakimtengstrand/IdeaProjects/spec-test/src/spec_test/core.clj:19:1)
> val: {:x "Elon"} fails spec: :common/user predicate: (contains? % :user/name)
>
>
> With this solution I don't need to enable assertions, and the code is neat 
> and less verbose!
>
> /Joakim
>
> On Thursday, September 15, 2016 at 3:11:32 PM UTC+2, Shantanu Kumar wrote:
>>
>> Hi Joakim,
>>
>> You might be interested in Paul Stadig's library 
>> https://github.com/pjstadig/assertions that leverages Java's `-ea` 
>> (enable-assertions, which you may want to keep enabled in dev) command-line 
>> flag. If you have a bunch of things together to assert, you may want to use 
>> the `when-assert` macro for wholesale optimization: 
>> https://github.com/pjstadig/assertions/blob/0.2.0/src/pjstadig/assertions.clj#L13
>>
>>
>> Shantanu
>>
>> On Thursday, 15 September 2016 16:50:17 UTC+5:30, joakim.t...@nova.com 
>> wrote:
>>>
>>> Ok, thanks!
>>>
>>> In the Java world, the assertions is also something that need to be turn 
>>> on explicitly.
>>> In that sence, they are kind of not mandatory to be executed (or at 
>>> least signals that to the reader of the code).
>>>
>>> I would be happier if you guys could add another method, that I can use 
>>> in my :pre conditions, that leverage
>>> the same amount of details in the error messages, but that is always 
>>> "turned on".
>>>
>>> In the meanwhile, I will use s/assert ;-)
>>>
>>> BR,
>>> Joakim Tengstrand
>>>
>>>
>>> On Wednesday, 14 September 2016 15:59:09 UTC+2, Alex Miller wrote:
>>>>
>>>> Another option that has been added since the guide was written is 
>>>> s/assert which seems closer to what you're suggesting.
>>>>
>>>> (defn name [user]
>>>>   {:pre [(s/assert :common/user user)]}
>>>>   (-> user :user/name))
>>>>
>>>> ;; need to enable assertion checking - this can also be enabled 
>>>> globally with system property clojure.spec.check-asserts
>>>> (s/check-asserts true)
>>>>
>>>> (name {:user/name "Elon"})
>>>> "Elon"
>>>>
>>>> (name {:x "Elon"})
>>>> ExceptionInfo Spec assertion failed
>>>> val: {:x "Elon"} fails predicate: (contains? % :user/name)
>>>> :clojure.spec/failure  :assertion-failed
>>>>   clojure.core/ex-info (core.clj:4725)
>>>>
>>>> Rather than use it in a precondition, you can also use s/assert 
>>>> directly in the code.
>>>>
>>>> On Wednesday, September 14, 2016 at 7:37:24 AM UTC-5, 
>>>> joakim.t...@nova.com wrote:
>>>>>
>>>>> (ns spec-test.core
>>>>>   (:require [clojure.spec :as s]))
>>>>>
>>>>> (s/def :user/name string?)
>>>>> (s/def :common/user (s/keys :req [:user/name]))
>>>>>
>>>>> ; first version of name (using :pre)
>>>>> (defn name [user]
>>>>>   {:pre [(s/valid? :common/user user)]}
>>>>>   (-> user :user/name))
>>>>>
>>>>> ; This statement works ok and returns "Elon":
>>>>> (name {:user/name "Elon"})
>>>>>
>>>>> ; but this statement...
>>>>> (name {:x "Elon"})
>>>>>
>>>>> ;...will throw:
>>>>> CompilerException java.lang.AssertionError:
>>>>> Assert failed: (s/valid? :common/user user)
>>>>>
>>>>> ; ...but then I don't get as much information
>>>>> ; about the error as if I would have called:
>>>>> (s/explain :common/user {:x "Elon"})
>>>>>
>>>>> ;...which also contains the predicate:
>>>>> val: {:x "Elon"} fails spec: :common/user
>>>>> predicate: (contains? % :user/name)
>>>>>
>>>>> ; (second version of name - more verbose)
>>>>> ; or do I need to wite it like this:
>>>>> (defn name [user]
>>>>>   (let [parsed (s/conform :common/user user)]
>>>>>     (if (= parsed ::s/invalid)
>>>>>       (throw (ex-info "Invalid input" (s/explain-data :common/user user)))
>>>>>       (-> user :user/name))))
>>>>>
>>>>> ; so that:
>>>>> (name {:x "Elon"})
>>>>>
>>>>> ; ...will return:
>>>>> CompilerException clojure.lang.ExceptionInfo:
>>>>>   Invalid input #:clojure.spec{:problems}
>>>>>     ({:path [], :pred (contains? % :user/name),
>>>>>       :val {:x "Elon"}, :via [:common/user], :in []})
>>>>>
>>>>> ; It should be nice if I could be able to write it like this
>>>>> ; (or similar, to get a better error message):
>>>>> (defn name [user]
>>>>>   {:pre [(s/explain :common/user user)]}
>>>>>   (-> user :user/name))
>>>>>
>>>>>

-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to