Fork me on GitHub
#clojure-spec
<
2020-11-10
>
Jim Newton16:11:17

I'm getting an error from spec that I don't understand. Maybe someone can help me. The following example, which I've based on an example in https://clojure.org/guides/spec, works fine, and valid? returns true.

(s/valid? (s/keys :req [::first-name ::last-name ::email]
                  :opt [::phone])
          {::first-name "Bugs"
           ::last-name "Bunny"
           ::email ""})
However, when I've programmatically generated the following list
(let [sss '(clojure.spec.alpha/keys
            :req [:clojure-rte.genus-spec-test/first-name
                  :clojure-rte.genus-spec-test/last-name
                  :clojure-rte.genus-spec-test/email]
            :opt [:clojure-rte.genus-spec-test/phone])]
  (s/valid? sss
          {::first-name "Bugs"
           ::last-name "Bunny"
           ::email ""}))
I get an uninformative exception
Execution error (ClassCastException) at (REPL:1).
null
is there a way to all s/valid? with a programmatically generated spec?

borkdude16:11:07

@jimka.issy An s-expression is not yet a spec. I would assume most people would write a macro for creating specs programmatically

Alex Miller (Clojure team)16:11:15

Yes, but you need to understand more about how spec works

Alex Miller (Clojure team)16:11:42

valid? works on spec objects

Alex Miller (Clojure team)16:11:01

Spec forms need to be evaluated into spec objects first

Alex Miller (Clojure team)16:11:53

In the case above, you could do that with eval

borkdude16:11:07

or generate the form with a macro

Alex Miller (Clojure team)16:11:58

Even so, you’re still leaning on eval

borkdude16:11:44

Made some fun macros the other day:

(def kws (map keyword (repeatedly gensym)))

(defmacro cat [& preds]
  `(clojure.spec.alpha/cat ~@(interleave kws
                                         (map expand-query preds))))
This allows you to write (g/cat int? string?), when you're not interested in the conformed value

Alex Miller (Clojure team)16:11:07

Spec 2 has a lot more tools for all this stuff

borkdude16:11:20

defop right?

borkdude16:11:31

any docs I could read yet?

Alex Miller (Clojure team)16:11:54

The wiki pages if you haven’t seen those

Alex Miller (Clojure team)16:11:30

But not everything is in there and it’s missing a lot of the internal design

borkdude16:11:39

I'll just wait, no hurry

Alex Miller (Clojure team)16:11:53

There is now an intermediate map data form now that you can work on directly

👏 3
Alex Miller (Clojure team)16:11:05

But will almost certainly change

borkdude16:11:18

Working with maps is a lot easier than writing macros (since macros beget more macros)

Alex Miller (Clojure team)16:11:34

Some day rich or I will do a talk about the internals - there are several interesting aspects of it

💯 3
👍 6
borkdude16:11:49

Looking forward

15
Jim Newton16:11:49

macros wont help in this case. the origin of my spec is not sitting in an evaluation position.

Alex Miller (Clojure team)17:11:19

evaluating a spec form gives you a spec object