Fork me on GitHub
#clojure-spec
<
2020-01-22
>
kenny16:01:42

I really like how succinct spec-tools data-specs are. It takes 17 lines worth of specs for a map that has a key that has a collection of maps down to 3 lines. Will Spec2 be able to do this as well? The syntax described here https://github.com/clojure/spec-alpha2/wiki/Schema-and-select#unqualified-keys looks quite similar. The description makes it sound like that syntax will only be available for unqualified keys though.

kenny16:01:45

Why not support qualified keys with that syntax?

kenny16:01:53

(s/def ::error-code string?)

(s/def ::error-message string?)

(s/def ::id uuid?)

(s/def ::failed-request
  (s/keys :req [::error-code ::error-message ::id]))

(s/def ::failed-requests
  (s/coll-of ::failed-request))

(s/def ::result
  (s/keys :req [::failed-requests]))
versus
(s/def ::result
  {::failed-requests [{::error-code    string?
                       ::error-message string?
                       ::id            uuid?}]})
The latter seems so much easier to read.

kenny16:01:16

Sorry, I don't follow. The latter could easily expand to do exactly as that doc describes.

kenny16:01:52

Well, I suppose the nested map wouldn't have a name.

Alex Miller (Clojure team)16:01:38

the objective here is not just to validate but to build a library of reusable (ie named + registered) specifications

kenny16:01:10

So Spec1 forces you to do that with unqualified keys. Why has that changed with Spec2?

Alex Miller (Clojure team)16:01:13

not sure I understand the question

kenny16:01:03

If I'm understanding the syntax here https://github.com/clojure/spec-alpha2/wiki/Schema-and-select#unqualified-keys, you are no longer creating a reusable specification for the nested map.

kenny16:01:13

Well, that I guess that applies for key & value in that ::order spec. Nothing is reusable.

Alex Miller (Clojure team)16:01:17

well, you are in the schema, but not in the sub levels. as unqualified names, they often are ambiguous

Alex Miller (Clojure team)16:01:27

you still can do like you did in spec 1 (relate unqualified keys to qualified specs) but it's not constrained to the unqualified name match and it's optional

kenny16:01:05

To be clear, the issue with something like this

(s/def ::result
  {::failed-requests [{::error-code    string?
                       ::error-message string?
                       ::id            uuid?}]})
Is that the nested map is not named?

Alex Miller (Clojure team)16:01:40

you're inventing syntax here, it can't be just considered in isolation

kenny16:01:21

Fair enough. I mean like this

(s/def ::order 
  (s/schema {:purchaser string? 
             :due-date inst?
             :line-items (s/coll-of (s/schema {:item-id pos-int? 
                                               :quantity nat-int?})
                           :kind vector?
                           :min-count 1
                           :gen-max 3)}))
but with every key qualified instead of unqualified.

Alex Miller (Clojure team)16:01:22

this now occupies the "map" slot in the language of specs, which may have other uses

Alex Miller (Clojure team)16:01:29

certainly, this goes against the grain of naming and registering the specifications. names have multiple utility in spec - they are used for spec reuse, but also in things like explain reporting, and I don't remember what else

Alex Miller (Clojure team)16:01:33

none of this rules out the possibility of adding more support for concise definition of multiple specs in tandem

Alex Miller (Clojure team)16:01:54

or even extension to support this in the future, but it's not our top concern

Alex Miller (Clojure team)16:01:46

and if we were going to do so, it would be driven by a top level problem, not just "it's a thing we can do".

kenny16:01:14

Understood. I don't think it necessarily goes "against the grain of naming and registering".

(s/def ::order
  (s/schema {::purchaser  string?
             ::due-date   inst?}))
That would register the ::purchaser spec as string? , ::due-date as inst? and ::order as "s/keys".

Alex Miller (Clojure team)16:01:23

what do you mean by 0.1.x and 0.2.x?

Alex Miller (Clojure team)16:01:44

are you talking specifically about spec.alpha?

Alex Miller (Clojure team)16:01:29

0.1.x is Clojure 1.9 era and 0.2.x is Clojure 1.10 era

Alex Miller (Clojure team)16:01:08

I don't think there were any breaking changes between those

Filipe Silva16:01:33

yes that is what I meant

Filipe Silva16:01:30

trying to update from cljs 1.10.520 to `1.10.597` causes my app to have a runtime error for optimized builds on what seems to be something spec related, so I thought there might be a breaking change

Alex Miller (Clojure team)16:01:59

what are 1.10.520 and 1.10.597 applicable to?

Alex Miller (Clojure team)16:01:07

oh cljs, sorry that got lost

Alex Miller (Clojure team)16:01:50

the cljs spec impl is inside ClojureScript so the stuff above does not directly correlate

Filipe Silva16:01:33

ah I see... so maybe I should ask about cljs.spec.alpha in #clojurescript instead

Alex Miller (Clojure team)16:01:50

I don't know anything on that

Filipe Silva16:01:05

coolio, thanks for the direction!