Fork me on GitHub
#clojure-spec
<
2019-06-12
>
carkh13:06:48

multi-spec dispatching on the first value in a sequence and returning the syntax for the rest of that sequence, possible at all ?

carkh13:06:06

all examples of multi-specs i could find were about maps

carkh13:06:31

what i'm trying to do : (s/def ::node (s/cat :tag keyword? (multispec dispatching on the tag here)))

Alex Miller (Clojure team)13:06:23

it is not only maps, can definitely be made to work with other things (I've got some stuff doing that)

Alex Miller (Clojure team)13:06:00

you can make your multimethod dispatch on first

Alex Miller (Clojure team)13:06:09

and then you have to be a little careful with the retag function

Alex Miller (Clojure team)13:06:23

I actually have an example of this in CLJ-2112 (specs on specs) I think

Alex Miller (Clojure team)13:06:24

you'll see spec-form is a defmulti on first

Alex Miller (Clojure team)13:06:59

and the ::spec spec uses (s/multi-spec spec-form (fn [val tag] val))

Alex Miller (Clojure team)13:06:26

and then the defmethods cover the different cases with different starting symbols

carkh13:06:43

thanks looking at your example

carkh13:06:16

ok got it working on the whole "sequence", i'm guessing this can't be done the way i want, dispatching on the first element in order to spec the rest of the sequence

carkh13:06:48

not a huge deal, just a little usability issue i guess

Alex Miller (Clojure team)13:06:21

isn't the example above what you're describing?

Alex Miller (Clojure team)13:06:50

I'm using it to spec a form sequence based on the operator type at the beginning, so seems like the same thing?

carkh13:06:27

(s/cat :tag keyword? :rest (s/multi-spec node-type :rest)) it looks like it's looking for a sequence in the rest

carkh13:06:03

the mmultispec is returning something like (s/cat ....) a flat thing

carkh13:06:32

is multispec like s/spec in this regard ?

carkh13:06:00

(i have a hard time following your example)

Alex Miller (Clojure team)13:06:07

you don't want an s/cat here at all - the multi-spec is the sequence spec

carkh13:06:39

but i need something to put around my stuff returned from the multimethod =)

carkh13:06:58

but yes i understand

Alex Miller (Clojure team)13:06:03

I don't understand what that meant

Alex Miller (Clojure team)13:06:13

the multimethod returns the spec for the sequence

carkh13:06:49

in the typical example for a typed map, you spec for the type keyword outside the multimethod

carkh13:06:12

then only spec for what's relevant to the multispec user in the multimethod

carkh13:06:56

but i think what i'm asking is impossible

Alex Miller (Clojure team)13:06:17

afaict what you're asking for is the example I gave. I don't get why it's not what you want.

Alex Miller (Clojure team)13:06:19

are you looking for something different in the conformed value shape?

carkh14:06:03

in your example, i want the :f #{'clojure.core/fn} out of the multimethod

carkh14:06:44

just like for the typical typed map examples

carkh14:06:10

actually i'm wrong on that

carkh14:06:54

event/type is indeed present in the multi-method in the guide

carkh14:06:39

ok then sorry for the noise ><

Alex Miller (Clojure team)14:06:11

you can post-process the conformed value to do whatever you want of course

carkh14:06:10

i was just weary that all the users of the multimethod will have to spec for the "tag"

carkh14:06:20

not a huge deal since all those users are me =)

carkh14:06:31

thanks for your time !

Alex Miller (Clojure team)14:06:40

yeah, you can just spec it as any? if you like

Alex Miller (Clojure team)14:06:58

it's already been chosen by the time you get into the multimethod and the value will flow through

Alex Miller (Clojure team)14:06:25

I spec'ed it in that code just for clarity

✔️ 4
colinkahn17:06:17

When multi-specing where the specs are s/keys and the retag is a keyword, is it best practice to include the retag key as :req in the defmethods keys spec?

Alex Miller (Clojure team)17:06:11

not sure what you mean by "include the retag key as :req"

Alex Miller (Clojure team)17:06:45

oh, you mean as a :req in the s/keys

Alex Miller (Clojure team)17:06:20

well it is probably required to get to that point in the first place

Alex Miller (Clojure team)17:06:03

and either way it's going to end up in the conformed value

Alex Miller (Clojure team)17:06:50

I'm not sure that it matters either way, depends on whether you see the retag key as part of the data or as frame around the data, but that's probably dependent on your code

colinkahn17:06:26

Ok cool, yeah I was doing it quite consistently in :req and ran into something where I was adding a :gen to the keys spec in the defmethod and found it a bit unergonomic to have to include the retag in the generator as well, which got me feeling like maybe it was better not to include it at all. I have been also specing the retag key mostly as something rather generic like keyword? too.