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 "<mailto:bugs@example.com|bugs@example.com>"})
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 "<mailto:bugs@example.com|bugs@example.com>"}))
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?@jimka.issy An s-expression is not yet a spec. I would assume most people would write a macro for creating specs programmatically
Yes, but you need to understand more about how spec works
valid? works on spec objects
Spec forms need to be evaluated into spec objects first
In the case above, you could do that with eval
or generate the form with a macro
Even so, you’re still leaning on eval
yep
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 valueSpec 2 has a lot more tools for all this stuff
defop
right?
That’s one
any docs I could read yet?
The wiki pages if you haven’t seen those
But not everything is in there and it’s missing a lot of the internal design
I'll just wait, no hurry
There is now an intermediate map data form now that you can work on directly
But will almost certainly change
Working with maps is a lot easier than writing macros (since macros beget more macros)
Some day rich or I will do a talk about the internals - there are several interesting aspects of it
Looking forward
macros wont help in this case. the origin of my spec is not sitting in an evaluation position.
thus, eval
evaluating a spec form gives you a spec object