(require '[clojure.spec :as s])
(require '[clojure.spec.test :refer [instrument]])
(defn request ([url]) ([params url]))
(s/fdef request
:args (s/cat :params (s/? map?) :url string?))
(instrument `request)
(request [] "")
ExceptionInfo Call to #'user/request did not conform to spec:
In: [0] val: [] fails at: [:args :url] predicate: string?
:clojure.spec/args ([] "")
:clojure.spec/failure :instrument
:clojure.spec.test/caller {:file "form-init1226863901212006294.clj", :line 1, :var-scope user/eval2193}
clojure.core/ex-info (core.clj:4725)
I expected that it would fail at `map?` predicate rather than at `string?` predicate.
s/or produces better explanation, but at the same time is relatively more verbose:
(require '[clojure.spec :as s])
(require '[clojure.spec.test :refer [instrument]])
(defn request ([url]) ([params url]))
(s/fdef request
:args (s/or :simple (s/cat :url string?)
:advanced (s/cat :params map? :url string?)))
(instrument `request)
(request [] "")
ExceptionInfo Call to #'user/request did not conform to spec:
In: [0] val: [] fails at: [:args :simple :url] predicate: string?
In: [0] val: [] fails at: [:args :advanced :params] predicate: map?
:clojure.spec/args ([] "")
:clojure.spec/failure :instrument
:clojure.spec.test/caller {:file "form-init1226863901212006294.clj", :line 1, :var-scope user/eval2208}
clojure.core/ex-info (core.clj:4725)