Fork me on GitHub
#clojure-spec
<
2019-04-27
>
kommen10:04:45

playing around with spec-alpha2, I was wondering if there is a way to make s/conform of an s/select only return keys of a map which are actually specified in the select.

kommen10:04:04

(s/def :foo/id string?)
(s/def :foo/text1 string?)
(s/def :foo/text2 string?)
(s/def ::foo (s/schema [:foo/id :foo/text1 :foo/text2]))
(s/def ::foo-only-text1 (s/select ::foo [:foo/id :foo/text1]))

(s/conform ::foo-only-text1 {:foo/id "bar" :foo/text1 "t1" :foo/text2 "t2"})
;; => #:foo{:id "bar", :text1 "t1", :text2 "t2"}

alexmiller16:04:56

No, by design

alexmiller16:04:30

It’s not working this way at the moment but select over a closed schema should throw invalid on that case

alexmiller16:04:57

The close stuff is going to get completely overhauled though so current api will change

dominicm14:04:55

I was curious about this, could you share what the current thinking is? Even with the disclaimer of it being heavy WIP?

alexmiller14:04:06

rather than the stateful api (which was intended to be similar to instrument), will be more op-specific, and actually more generic than just "closing", will open up some api space for other kinds of checking variants

alexmiller14:04:38

so, new options on valid?, conform, assert, etc - anything with checking

dominicm14:04:09

Sounds really interesting. Looking forward to seeing how much leverage this provides.

ikitommi08:04:40

checking variants like runtime transformations / coercion? or just validating? anyway, generic sounds great. :+1:

alexmiller11:04:26

Not transformations

metametadata15:05:01

> so, new options on valid?, conform, assert, etc - anything with checking it looks like it will create friction for adopting closed maps in defn-spec and other libs which don't know about new options in the methods and rely on the fact that every spec itself describes everything needed for validation

alexmiller15:05:09

that's something defn-spec will have to reckon with. function specs themselves are going to go through significant changes and making an integrated defn+function spec syntax is in scope.

metametadata15:05:42

thanks. fwiw, this is the typical way I add specs to protocol methods using defn-spec at the moment (`sp` here contains custom spec helpers):

(:require [common.logic.specs :as specs]
            [spec-plus.core :as sp]
            [clojure.spec.alpha :as s]
            [defn-spec.core :as ds]))

(defprotocol Protocol
  (-fetch-places [_ postal]))

(ds/defn-spec fetch-places
  {::s/args (sp/pos any? ::specs/postal)
   ::s/ret  (sp/seq-of ::specs/place)}
  [this postal]
  (-fetch-places this postal))

dominicm15:05:12

I guess there's a open question of whether the function level is the right place for deciding closedness. Maybe the other flags will clarify this.

metametadata15:05:53

yes, it's interesting to see how function specs will play with closed maps. and speaking of that, this is how I use closed maps in functions currently:

(ds/defn-spec build-and-push
  {::s/args (sp/pos ::component
                    (sp/speced-keys :req-un [::path ::image-id ::tag]))} ; sp/speced-keys implements a closed s/keys spec
  [component {:keys [path image-id tag]}]
...

dominicm15:05:56

I'm suggesting that maybe it's up to the caller sometimes whether to apply certain constraints.

alexmiller15:05:31

these flags will probably be available on calls like instrument or check so you could supply those constraints that way

metametadata15:05:33

would be cool if it allowed to spec a function in such a way that some args are closed and some are not, e.g. (foo <closed-map> <integer> <open-map>)

dominicm15:05:38

That sounds like an important filter.

alexmiller16:05:47

the planned api will allow that

alexmiller16:05:42

well, on a per-spec basis that is. if you want to use the same spec in both modes in a single context, not sure about that (or whether that's even a real use case)

dominicm17:05:40

Hmm, merging an old-user with new-user where the new user is coming over the wire and needs to be locked down, but old-user is from the db?