Fork me on GitHub

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.


(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"}


No, by design


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


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


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


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


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


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


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


Not transformations


> 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


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.


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))


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.


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]}]


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


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


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>)


That sounds like an important filter.


the planned api will allow that


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)


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?