Fork me on GitHub

hey all. so are spec’s searchable in anyway?


let’s say I have (s/def ::a string?)


and (s/def ::b (s/keys :req-un [::a])


and I want to know if ::b contains any values that are strings?


is it serious effort to find this out?

Geoffrey Gaillard10:04:51

@triss I don't think there is a function for that purpose. But (s/form spec) give you the spec form, so in your case the list (s/def ::b (s/keys :req-un [::a]). You could walk it like a tree and recursively s/form any spec you find until you get a predicate that match you search criteria … I do something similar to extract the set of keys used by nested s/merge specs. Maybe there is a cleaner way to do it though…

Geoffrey Gaillard10:04:58

Do you know if there is a way to make spec generate a minimalist sample for a particular spec ? What I mean by minimalist is "the first simplest value validating the predicate". If I have (s/nilable string?) I'd like to get nil, if I have string?, I'd like to get "", if I have (s/coll-of ::foo :kind vector?) I'd like to get []. I don't know (yet) how spec works internally but I would expect it could be able to find the shortest path to the first and simplest value validating the predicate. It would be really useful to generate kind of placeholder data waiting to be filled but still validating the spec. Especially when building forms with Re-Frame or similar frameworks.


Has anyone seen a similar error message like this lately? Attempting to call unbound fn: #’clojure.spec/macroexpand-check We get it in our ClojureScript build. We’re using clojure.future.spec alpha15.

Alex Miller (Clojure team)12:04:06

@triss there is no easy way to figure that out right now

Alex Miller (Clojure team)12:04:24

@ggaillard you can call gen/sample and take the first example. Samples "grow" in complexity as you use a generator so the first few are usually "simple"


hi, I have a (defspec tester 100.... in my test file... but when I run either lein test or from the REPL it seems to run only once. Any idea what could cause this?


how do you fdef a fn without args?

Alex Miller (Clojure team)15:04:10

(s/fdef foo :args (s/cat))

Alex Miller (Clojure team)15:04:40

although it may not be worth defining a spec for a no-arg function

Alex Miller (Clojure team)15:04:34

as you can’t check its args via instrumentation and generative testing is likely not too useful


well, this method will grow to support multiple parameters, so that's why i wondered in the first place


i already found out that s/+ works for that


just wondered how to do no parameters

Alex Miller (Clojure team)17:04:02

(s/fdef foo :args (s/* any?)) (with a suitable spec instead of any?) will support 0 or more args


is there a way to make a s/keys take a var in the req list?

(let [k :ns/kw] (s/explain (s/keys :req [k]) {:ns/not-kw "hello"})) => Success!

Alex Miller (Clojure team)21:04:43

not easily - you can use macro or eval to do so


curious why the above doesn’t work?

Alex Miller (Clojure team)21:04:40

because s/keys is a macro and expects a literal vector of keywords in :req, not something that is evaluated

Alex Miller (Clojure team)21:04:01

in the example above, everything that’s not a keyword (`k`) is just being ignored

Alex Miller (Clojure team)21:04:53

it’s being interpreted as (s/explain (s/keys :req []) {:ns/not-kw "hello"})


makes sense, thanks