Thank you the pointers! So far I ended up with writing a small `map` macro which is similar to `s/keys` but checks that keys are already in the registry: https://gist.github.com/metametadata/5f600e20e0e9b0ce6bce146c6db429e2
On Monday, October 2, 2017 at 10:03:57 PM UTC+3, Beau Fabry wrote: > > fwiw, I vote for leaving it. It's extra flexibility and is afaict a fairly > easy error to catch. Here's a function that I think should give you every > qualified keyword that is used in a spec but that does not have a spec > defined for it: > boot.user=> (let [kws (atom #{})] > #_=> (clojure.walk/postwalk (fn [x] (when (qualified-keyword? x) > (swap! kws conj x)) x) (map s/form (vals (s/registry)))) > (clojure.set/difference @kws (set (keys (s/registry)))) > #_=> ) > #{:clojure.spec.alpha/v :clojure.spec.alpha/k} > boot.user=> > > On Monday, October 2, 2017 at 10:30:57 AM UTC-7, Leon Grapenthin wrote: >> >> I second this from my experience, using spec quite extensively since its >> release. >> >> We already had some invalid data passing silently because of this. It can >> easily happen if you have a typo in the spec. >> >> Also we never experienced benefits from being able to not spec keys >> required in s/keys. It appears to be a pretty obsolete feature, making >> vulnerabilities more likely. >> >> On Monday, October 2, 2017 at 5:37:31 PM UTC+2, Yuri Govorushchenko wrote: >>> >>> Hi! >>> >>> I have some noobie questions for which I couldn't google the compelling >>> answers. >>> >>> 1) Is there any way to ensure that the keys I used in `s/keys` have the >>> associated specs defined? At compile time or at least at runtime. Maybe via >>> an additional library? I could imagine a macro (smt. like `s/keys-strict` >>> or `s/map-pairs`, as maps can also be viewed as sets of spec'ed pairs) >>> which additionally checks that all keys have specs registered. I'm OK with >>> sacrificing some flexibility (e.g. being able to define key specs after map >>> specs, dynamically, etc.) in favour of more strictness. >>> >>> Motivation: I don't fully trust my map validation code when using >>> `core.spec`. `s/keys` doesn't require that the key has the spec registered >>> to validate its value. Although this may be flexible but in practice can >>> lead to errors. Specifically, it's quite easy to forget to create a spec >>> for a key, mistype it or forget to require the namespace in which key spec >>> is defined (e.g. if the common key specs reside in a dedicated ns): >>> >>> ``` >>> ; totally forgot to define a spec for ::foo >>> (s/def ::bar (s/keys :req [::foo])) >>> >>> ; fooo vs. foo typo >>> (s/def ::fooo string?) >>> (s/def ::bar (s/keys :req [::foo])) >>> >>> ; :common/foo vs. ::common/foo typo >>> (s/def ::bar (s/keys :req [:common/foo])) >>> >>> ; didn't require common.core ns (spec for :common.core/foo is not added >>> to global registry) >>> (s/def ::bar (s/keys :req [:common.core/foo])) >>> ``` >>> >>> These subtle mistakes can lead to map validations passing silently (as >>> long as keysets are correct). >>> >>> Related to this: there're feature requests for Cursive IDE which try to >>> address typing and reading mistakes related to keywords, e.g. >>> https://github.com/cursive-ide/cursive/issues/1846 and >>> https://github.com/cursive-ide/cursive/issues/1864. >>> >>> After using Schema for a while it's difficult to appreciate the way >>> `core.spec` defines it's own global registry which uses keywords instead of >>> using spec instances and good old variables, especially since Cursive IDE >>> has quite a nice support for variables already. But I think this is another >>> topic which was already discussed, e.g. in >>> https://groups.google.com/forum/#!topic/clojure/4jhSCZaFQFY ("Spec >>> without global registry?"). >>> >>> 2) What is the motivation for library having a "loose" default behaviour >>> of `s/keys` and no "strict" variant at all for spec-ing both keys and >>> values at the same tome? I think in majority of cases I'd need to spec both >>> keys and values of the map instead of only keys and would expect the >>> library to have built-in API for this. Maybe for the future references it >>> would be beneficial to add concrete code examples into motivation in the >>> core.spec guide ( >>> https://clojure.org/about/spec#_map_specs_should_be_of_keysets_only) >>> which would better illustrate the described benefits of the current lib >>> behaviour? >>> >>> Thanks. >>> >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.