Fork me on GitHub
#clojure-spec
<
2017-08-28
>
danielcompton03:08:17

Is there a way to spec a nested map that dispatches on type? e.g.

(s/def :app/command (s/keys :req [:command/id
                              :command/params
                              :request/id
                              :idempotency/id]))

(defmulti command-params :command/id)
(s/def :command/params (s/multi-spec command-params :command/id))

(defmethod command-params :test/command [_]
  (s/keys :req [:material/id]))

;; This is the kind of map shape I want

{:command/id     :test/command
 :request/id     (random-uuid)
 :idempotency/id (random-uuid)
 :command/params {:test/id (random-uuid)}}

danielcompton03:08:57

I thought I could do this with a multi-spec, but I'm not sure how to define a multi-spec where the data is at one level, and the tag is at the parent level

ikitommi07:08:38

Idea: s/conform could be changed into s/walk that could be parametrised to do either :conform (as now) or :coerce (like conform, but would not return the branch-information, e.g. same results as with conform + unform).

ikitommi07:08:17

I think this would yield much better perf, which matters at runtime.

scaturr13:08:28

Is there any sort of consensus on where to put specs? Separate ns? Same ns as things being specced?

souenzzo15:08:23

+subscribe+

seancorfield15:08:43

It Depends(tm).

seancorfield16:08:32

Data specs can usually be in their own ns, possibly with a few predicate functions or closely related helper functions.

seancorfield16:08:36

Function specs probably should be in the same ns as the functions they are spec'ing -- unless you need to support Clojure 1.8 (or earlier) as well as Clojure 1.9, such as for a library, in which case they must go in a separate, optional ns, that only 1.9 users will load.

scaturr16:08:35

that is super helpful. thank you!

scaturr13:08:46

Tooling makes me feel like the same ns might be more convenient - not necessarily better?

scaturr13:08:26

for instance cider’s doc command doesn’t work unless you explicitly have the spec required

scaturr13:08:39

¯\(ツ)

hmaurer17:08:47

is there a way to “override” an already defined spec?

hmaurer17:08:51

(with s/def)

hmaurer17:08:01

it’s a no-op for me if the spec is already defined

seancorfield18:08:44

Remember that s/def will only update the spec -- not all the other specs that have been defined in terms of that spec.

Alex Miller (Clojure team)00:08:18

yeah, this should work (once you re-def the other specs)

hmaurer17:08:12

Found my answer: hacky (reset! @#'spec/registry-ref {})

hmaurer18:08:20

actually that seems to break things…

joshjones20:08:24

i’m not shocked