Fork me on GitHub
#clojure-spec
<
2020-01-14
>
mping11:01:42

is there a way to spec a map according to its key? example: if key is a number, value should be a number, if key is something else then value should be a string

Alex Miller (Clojure team)13:01:33

Yes, although it’s a little complicated

Alex Miller (Clojure team)13:01:02

The structure is to spec it as a s/coll-of s/tuples, where each tuple is an s/or of whatever key/value is allowed

Alex Miller (Clojure team)13:01:38

The coll-of should also have an :into {}

favila13:01:55

something like

(s/coll-of (s/or :num-val (s/tuple number? number?)
                 :string-val (s/tuple (s/and any? (complement number?)) string?))
           :into {})

mping16:01:27

got it, tks!

colinkahn17:01:02

I ran across something unexpected when using spec alpha v1:

(s/def ::foo number?)
(s/def ::bar-ret ::foo)
(gen/generate (s/gen ::bar-ret {::bar-ret #(gen/return 100)}))
;; => -2123123
this seems to be because when overrides are applied it determines the key to pull from the overrides map using something like this:
(let [s (@#'s/specize ::bar-ret)]
  (@#'s/spec-name s))
;; => ::foo
and like that shows ::bar-ret returns ::foo. My question is whether this is by design or perhaps a bug, and is it too hacky using something like (s/def ::bar-ret (s/spec ::foo)) to get this to work?

Alex Miller (Clojure team)17:01:33

this is a known bug (there's a ticket for it) and we plan to fix in spec 2

Alex Miller (Clojure team)17:01:42

your workaround is fine

colinkahn17:01:50

Awesome, thanks!