Fork me on GitHub
#clojure-spec
<
2018-01-12
>
stijn15:01:06

how can you define or alter specs programmatically? I have my data model defined in an edn file and like to generate specs based on that

stijn15:01:13

(let [k :my.ns/foo
      values integer?]
  (s/def k values))
=> user/k
(s/describe :my.ns/foo)
Exception Unable to resolve spec: :my.ns/foo  clojure.spec.alpha/reg-resolve! (alpha.clj:69)
(s/describe 'user/k)
=> values

mpenet15:01:43

with eval, or a macro

kenny23:01:25

I'm confused why the first s/keys call does not work and the second one does:

(def my-keys [::a])
=> #'user/my-keys
(s/keys :req my-keys)
java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
(s/keys :req (conj my-keys ::b))
=>
#object[clojure.spec.alpha$map_spec_impl$reify__1931 0x2d5c83e "clojure.spec.alpha$map_spec_impl$reify__1931@2d5c83e"]

kenny23:01:32

And it's not that it just compiles. The conj is actually evaluated:

(s/valid? (s/keys :req (conj my-keys ::b))
          {::a "a"
           ::b "b"})
=> true
(s/valid? (s/keys :req (conj my-keys ::b))
          {::a "a"})
=> false

gklijs23:01:16

It's because in the first one you suply a symbol, while in the second a list. Not really sure why though.