Fork me on GitHub
#clojure-spec
<
2016-11-26
>
lvh03:11:04

Is there a way to specify that I expect the value of a var to be valid according to a particular spec, such that it is automatically tested?

lvh03:11:43

Sometimes they’re just data structures, but they might also be the result of a higher order function

lvh04:11:30

Also; why isn’t there a map-of that takes specs instead of preds?

seancorfield05:11:11

@lvh map-of does take specs...?

seancorfield05:11:35

(s/map-of ::foo ::bar) works...

Alex Miller (Clojure team)06:11:44

@lvh you could just check s/valid? when you set the var. You can use set-validator! on vars but I’m assuming you’re not actually changing it after you set it.

kestrel713:11:44

Is it possible to inspect a spec to get, e.g., the list of keys defined by (s/keys :req [a b c])? I’ve created a spec for a map and want to retrieve the list of keys expected for that map for a purpose other than checking the spec.

dergutemoritz13:11:43

@kestrel7 clojure.spec/form is what you're looking for

kestrel714:11:36

Perhaps a noob question but from that how do I extract the actual list of keys from the resulting structure, which in this case looks like the following example but could I guess be more complex? Naively I could just say (last (s/form the-spec)) but that’s not going to be robust if the form contents change. (clojure.spec/keys :req [:k.specs.person/title :k.specs.person/first-name :k.specs.person/other-names :k.specs.person/last-name])

dergutemoritz14:11:27

That's the tricky bit, hehe

kestrel714:11:29

I guess I could use core.match somehow. It would be useful to get the spec as data that’s easier to interrogate. Thanks for the help @dergutemoritz

dergutemoritz14:11:34

You can do something like that for the simple case of a single s/keys spec. However, when stuff like s/merge is involved, it gets a lot trickier

dergutemoritz14:11:57

It would be useful to have specs for those forms so you could s/conform them.

kestrel714:11:02

For the moment I’m going to cheat: (def the-keys [::a ::b ::c] (s/def ::m (s/keys :req the-keys)

dergutemoritz14:11:30

I'm not sure if anyone has put effort into defining such specs already. I was gonna take a stab at that myself when I find some time

dergutemoritz14:11:43

@kestrel7 That cheat won't work I'm afraid

dergutemoritz14:11:04

The keys vector needs to be literal IIRC

dergutemoritz14:11:25

Because it's processed at macro expansion time

dergutemoritz14:11:43

Right, just try it in the REPL and you'll see

kestrel714:11:02

@dergutemoritz you’re right 😞

dergutemoritz14:11:20

@kestrel7 (apply hash-map (rest (s/form your-keys-spec))) should give you a reasonable data structure to work with for bare s/keys specs

kestrel714:11:29

Here’s my workaround for now

kestrel714:11:51

(defn spec-keys "Return the :req keys from the spec" [spec] (let [spec-form (s/form spec)] (assert (= 'clojure.spec/keys (first spec-form))) (:req (apply hash-map (rest spec-form)))))

dergutemoritz14:11:15

Should do the trick

dergutemoritz14:11:37

You could destructure spec-form right there in the let but I guess that's just cosmetics 🙂

lvh15:11:09

@seancorfield huh! I knew that compiled but I assumed it was treating the keyword as a predicate

dergutemoritz16:11:51

Is there a way to unwrap a regex op context that was previously created with s/spec?

dergutemoritz16:11:17

Hmm regex-spec-impl doesn't look like it offers something like that

Alex Miller (Clojure team)18:11:15

I have specs for all the forms and those will be published, but I'm still working through fixing all the bugs in form first

Alex Miller (Clojure team)18:11:39

With those, you will be able to conform any spec form to get at its parts

dergutemoritz19:11:44

Ah heck 🙂 throws his Saturday afternoon hack into the trash bin

dergutemoritz19:11:19

Well, I'll keep it around, perhaps I came up with some things that could be added to your implementation