Fork me on GitHub

How do I instrument/unstrument functions on a per-namespace basis?

Jakub Holý (HolyJak)06:05:15

(st/instrument (st/enumerate-namespace 'my.core)) Enum. enumerates all vars but instrument seems to be happy with that and presumabely skips those that are not spec-instrumentable.


that's just what I was looking for, thanks!


(stest/instrument (map symbol (vals (ns-interns *ns*))))


am i missing something regarding s/union and s/select? i’m trying to do something like this:

(require '[clojure.spec-alpha2 :as s])
(s/def ::n number?)
(s/def ::o odd?)
(s/def ::schema1 (s/schema [::n]))
(s/def ::union1 (s/union ::schema1 [::o]))
(s/select ::union1 [*])                  ;; => IllegalArgumentException
(s/select (s/union ::schema1 [::o]) [*]) ;; => IllegalArgumentException

Alex Miller (Clojure team)12:05:30

probably broken atm. top-level union is probably going to go away anyways

👍 4
Alex Miller (Clojure team)12:05:44

I'll take a look when I next get a chance


ok, perfect. appreciate the info!


could the s/def fail-fast on totally bogus spec-forms? what would be a spec for the spec-form arg in s/def?


(s/def ::a 1)
;; :user/a

(s/valid? ::a 1)
;; Syntax error (ClassCastException)
;; java.lang.Long cannot be cast to clojure.lang.IFn

Alex Miller (Clojure team)19:05:40

it could check some things better, for sure

Alex Miller (Clojure team)19:05:54

what's valid is changing between spec 1 and 2

Alex Miller (Clojure team)19:05:48

in spec 2 the valid symbolic forms are keywords, sets, symbols, and lists/sequences which are spec forms where a known spec op is in op position (ops are an extension point via multimethod)

Alex Miller (Clojure team)19:05:17

we may add another datafied/map form, still tbd

Alex Miller (Clojure team)20:05:28

notably, function objects are not allowed (different than spec 1)


hey all, does anyone know why can’t I do something like this with spec?

(s/def ::profile (s/keys :req-un {::id int?
                                                      ::name string?
                                                       ::photos (s/* (s/keys :req-un {::type int?}))}))

Alex Miller (Clojure team)20:05:08

you mean, inline a spec in s/keys?

Alex Miller (Clojure team)20:05:54

by design, spec is trying to enable a shared global registry of attribute specs

Alex Miller (Clojure team)20:05:24

the attribute spec is considered to be more important than containers of those attributes

Alex Miller (Clojure team)20:05:56

as such, we require you to strongly associate a spec with an attribute name

Alex Miller (Clojure team)20:05:47

spec 2 will have more support for inlining attribute spec defs for unqualified keys (common with json interop)


I see. Being new to spec I find that not being able to inline specs makes it harder for me to reason about them but I suppose that might change once I get more familiar with it, and one I learn about the best practices on creating specs (any suggested links?).


btw, thanks for the response @alexmiller


curious if there is a significant expected runtime difference between computing s/selects dynamically and defing them prior. e.g. if the following s/valid calls were going to be called in a loop:

(require '[clojure.spec-alpha2 :as s])

(s/def ::schema1 (s/schema [...]))
(s/def ::select1 (s/select ::schema1 [...]))
(def select2 (s/select ::schema1 [...]))

(s/valid? ::select1 {...})
(s/valid? select2 {...})
(s/valid? (s/select ::schema1 [...]) {...})

Alex Miller (Clojure team)21:05:45

you should expect that we have spent no time yet on perf aspects of select :)

😂 4
👍 4
Alex Miller (Clojure team)21:05:29

in general though, the first two are reusing the same spec object, which means work can be done once at spec object creation time (optimization work is basically shifting as much work as possible into construction time here) whereas the last one would pay that cost every time

💯 4

exactly—was about to say that i suppose i’d always def it, if it weren’t truly dynamic. was just tangentially curious about the perceived cost of the dynamism there

Alex Miller (Clojure team)21:05:03

so in general, I would tend toward either using an object saved in var or from the registry (those are probably approx the same)

👍 4
Alex Miller (Clojure team)21:05:45

but also note that the tradeoff, as usual, is in not picking up changes to specs in the ... there

Alex Miller (Clojure team)21:05:17

so you might make the opposite choice at the repl, if you're in development

Alex Miller (Clojure team)21:05:29

generally, I am just working in a file, that has all the specs I'm working on in it, and I just reload the file, which registers and recompiles all of the specs, and I don't care

Alex Miller (Clojure team)21:05:42

it is useful to have that mental model though


right, right. got it. thats a premium tip. spec2 is awesome, have been having a blast getting some experience. it alleviates essentially all of my old s/keys woes 🥳