Fork me on GitHub
#clojure-spec
<
2021-12-16
>
danieroux13:12:31

(require '[clojure.spec.alpha :as s])
  
  (s/def ::not-in-map-spec pos-int?)
  (s/def ::in-map-spec string?) 
  (s/def ::the-map 
    (s/keys :req [::in-map-spec]))
  
  (def m 
    {::in-map-spec     "yes"
     ::not-in-map-spec -13})
  
  (s/valid? ::the-map m) ; => false
  (s/explain ::the-map m) ; => -13 - failed: pos-int? in: [:user/not-in-map-spec]

danieroux13:12:14

This surprises me, that a key that’s not in my spec, makes the spec invalid?

Alex Miller (Clojure team)13:12:08

This is covered in the docstring for s/keys - all keys are checked

danieroux13:12:42

Hmm. That’s a conundrum in my usage, which I assume questions my usage: I have a big-map. I want to grab a part of it and save it away. Then use the rest to flow along. I can’t grab a part of it, because the rest is invalid. Do I explicitly select-keys to save it away?

pavlosmelissinos19:12:01

(s/def :demo/m1 (s/keys :req-un [::a ::b ::c ::d ::e]))

(s/def :demo/m2 (s/keys :req-un [::a ::b ::c]))
Does spec provide a way to go from m1 to m2 programmatically? (I suppose I'm looking for the inverse of s/merge)

Alex Miller (Clojure team)20:12:38

spec is not a transformation engine, it's a validation/verification library

Alex Miller (Clojure team)20:12:59

or are you asking about spec transformation

Alex Miller (Clojure team)20:12:01

assuming so, not really, it really encourages building up by composition, not by taking away

👍 1
pavlosmelissinos20:12:13

I meant spec transformation, yes. I'm writing generative tests based on some s/keys specs and I'll have to dissoc some of the keys after the generation anyway, so I wondered if I could skip that step. Definitely not a deal-breaker and the justification behind the design decision is sound, as always. Thanks. 🙂