Fork me on GitHub
#clojure-spec
<
2019-06-27
>
Jakub Holý (HolyJak)11:06:15

Is it possible to "and the rest of the arguments should match this others spec"? Example:

(s/def ::kid (s/cat :name string? :age int?))
(s/def ::input-explicit-username (s/cat
                                   :username uuid?
                                   :kid ::kid))
(s/def ::input (s/or :implicit-user ::kid, :explicit-user ::input-explicit-username))
The thing is that I either have a short input or something+the short input. How to spec this without copy&paste? Thank you! Answer: s/cat do not nest, they become one so the code above actually works as desired:
(s/conform ::input ["name" 12])
=> [:implicit-user {:name "name", :age 12}]
(s/conform ::input [(java.util.UUID/randomUUID) "name" 12])
=> [:explicit-user {:username #uuid"c19bc1f5-033f-4ca1-b2e0-5877657cfa8d", :kid {:name "name", :age 12}}]

👍 4
misha12:06:10

If you want some of regex specs to match nested structure, wrap them in s/spec, @holyjak

Jakub Holý (HolyJak)13:06:04

thx! I wouldn't figure that one out 🙂

misha12:06:02

(s/+ int?) matches 1 2 3 (s/spec (s/+ int?)) matches (1 2 3) s/def wraps form in s/spec, so from (s/def ::x (s/+ int?)) it might appear that (s/+ int?) matches (1 2 3) (with parens). It does not.

Alex Miller (Clojure team)12:06:40

I wouldn't say it that way

Alex Miller (Clojure team)12:06:55

user=> (s/valid? (s/+ int?) [1 2 3])
true
user=> (s/valid? (s/spec (s/+ int?)) [1 2 3])
true

Alex Miller (Clojure team)12:06:31

the more accurate way to look at it is that (s/+ int?) is a regex op (which is not actually a spec)

Alex Miller (Clojure team)12:06:53

when used, regex ops are automatically "spec-ized"

Alex Miller (Clojure team)12:06:06

s/spec is an explicit "spec-ize" step

Alex Miller (Clojure team)12:06:55

in all cases, regex ops are matching the elements in a sequential collection though

misha14:06:17

That’s what I meant kappa

kappa 4
parrot 4
Alex Miller (Clojure team)14:06:56

I realize that, it's just the wrong mental model

💯 4
jeroenvandijk16:06:25

Is it a good practise to use keyword inheritance for multi-spec dispatch? e.g.

(defmulti example-config :entity/type)

(s/def :entity/type #(contains? (set (methods example-config)) %))

(defmethod example-config :default [_]
  (s/keys :req [:entity/type]))

(s/def :entity/config (s/multi-spec example-config :entity/type))

(defmethod example-config :entity.type/generic [x]
  (getx x :entity/type))


;; Use keyword inheritance to get to the right spec
(derive :entity.type/specific :entity.type/generic)

(s/def :entity.type/specific integer?)

(s/explain-data :entity/config {:entity/type :entity.type/spfecific})

Alex Miller (Clojure team)17:06:32

not sure if there are any gotchas in gen, but might be

jeroenvandijk18:06:27

Thanks, I'll give it a go. Removes some boiler plate code