Reputation: 3337
Can I use the Clojure spec system to define function signatures and verify if functions satisfy them?
Here are some examples I've tried without success
(s/valid? (s/fspec :args string? :ret string?) identity) ;; false
(def nope identity)
(s/valid? (s/fspec :args string? :ret string?) nope) ;; false
(s/conform (s/fspec :args string? :ret string?) identity) ;; invalid
(defn strmap [s] {:pre [(s/valid? string? s)] :post [(s/valid? string? %)]} s)
(s/valid? (s/fspec :args string? :ret string?) strmap) ;; false
(s/fdef strmap :args string? :ret string?)
(s/valid? strmap strmap) ;; true
(s/def ::str-pred (s/fspec :args string? :ret boolean?))
(s/valid ::str-pred (fn [s] true)) ;; false
I know about fdef
, but I'd like something I can compose. For example, creating a map of related function signatures.
Upvotes: 0
Views: 698
Reputation: 3337
Turns out spec does handle functions, but it expects the arguments to be a tuple.
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) identity) ;; true!
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] (str x "hi there"))) ;; true
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] x)) ;; true
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] 42)) ;; false
There does appear to be some issues with the anonymous function literal. I'm probably misunderstanding something about the macro expansion.
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) #(%)) ;; false
Upvotes: 0
Reputation: 34790
You can access the :args
and :ret
spec of a function using s/get-spec
and then validate:
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (defn strmap [s] s)
#'user/strmap
user=> (s/fdef strmap :args string? :ret string?)
user/strmap
user=> (s/valid? (:args (s/get-spec `strmap)) "foo")
true
user=> (s/valid? (:args (s/get-spec `strmap)) :bar)
false
I am using this in re-find.web.
Upvotes: 4
Reputation: 2201
An alternative to clojure.spec
, malli
is a data-driven schema library that has support for function schemas
Upvotes: -1