> The argument that existence of specs provided to s/keys can only be checked at runtime is false.
> The argument that that recursive specs are impossible if existence of specs provided to s/keys was checked at compile time is also false. Could you explain to us why this is false? Clojure is a dynamic language, as such I don't see how you could define a time when all specs need to be present. How would I enter this spec at the repl if spec definition was required at s/keys invocation time? boot.user=> (s/def ::val string?) :boot.user/val boot.user=> (s/def ::tree (s/keys :opt-un [::val ::branches])) :boot.user/tree boot.user=> (s/def ::branches (s/tuple ::tree ::tree)) :boot.user/branches On Friday, October 6, 2017 at 4:32:41 PM UTC-7, Leon Grapenthin wrote: > > The argument that existence of specs provided to s/keys can only be > checked at runtime is false. > > The argument that that recursive specs are impossible if existence of > specs provided to s/keys was checked at compile time is also false. > > The usecase for libraries is not convincing: If the libraries author > states "the map has to have a key K" nobody can spec K further since that > would be a race condition among consumers (who s/defs K first?). Requiring > the libraries author to declare K as any? would at least require him to > decide and convey his intent. > > The argument that not checking a value associated with a key is > corresponding to a guding design principle of map specs being based on a > keyset is not stating enough to justify discussed behavior. The utility of > knowing that a keyset is present is close to none, which should be the main > reasons why s/keys validates values. Again: Saying "A map that has a key > called ::foo" is pretty pointless in Clojure. If every map in every Clojure > program I wrote had a key ::foo they would all produce the exact same > results as if they didn't and I bet yours would, too. > > Prototyping is indeed a bit more easy if one does not have to to declare > every spec used in a s/keys. However, that is particularly damning if you > forget to add that spec later or mistype its name when doing so. Which > happens, and which is why I'm unhappy with this design letting such typical > human errors pass compilation. It would also help my prototyping needs if I > could reference symbols that are not declared, but I prefer the compiler > errors before going live. > > On Saturday, October 7, 2017 at 12:01:34 AM UTC+2, Sean Corfield wrote: >> >> As one of the (apparently pretty uncommon) users who actually does >> happily define s/keys specs without correspondingly speccing the leaves as >> an "incrementally lock down/validate" approach, I wouldn't be too upset if >> I lost that ability and it started throwing an error. I mean it throws an >> error if I go to generate it anyway. >> >> >> >> **puts hand up!** >> >> >> >> I don’t want to have to write (s/def ::some-key any?) all over the place >> as I’m developing specs, just to satisfy an overly eager checker (in my >> mind). Worse, since the check would need to be deferred until validation >> time, as Beau notes, the omission of an “any?” key spec might not even show >> up until much further down the line. >> >> >> >> To me, this default behavior of silently not checking the _*value*_ >> associated with a _*key*_ is in keeping with the design principles of >> spec which focus on maps being based on a *key set*, while offering >> functions to allow you to optionally check values. >> >> >> >> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN >> An Architect's View -- http://corfield.org/ >> >> "If you're not annoying somebody, you're not really alive." >> -- Margaret Atwood >> >> >> ------------------------------ >> *From:* clo...@googlegroups.com <clo...@googlegroups.com> on behalf of >> Beau Fabry <imf...@gmail.com> >> *Sent:* Friday, October 6, 2017 9:10:36 AM >> *To:* Clojure >> *Subject:* Re: [core.spec] Stricter map validations? >> >> A use case that comes to mind is a system/library that specifies the >> structure of some inputs/outputs, but lets users/consumers (optionally) >> specify further validation of the leaves. I suppose that would be possible >> with (s/def ::foo any?) but you'd have to be a bit more careful about load >> order. The other use case (which is mine) is I'm just lazy and only want to >> write out broad strokes specs sometimes without getting into the nitty >> gritty. >> >> If s/keys were to validate that the keys it's provided have specs it >> would have to do it at validation time, so you wouldn't get the error until >> something was actually validated against that key spec. Trying to do it at >> definition time would break recursive specs. >> >> As one of the (apparently pretty uncommon) users who actually does >> happily define s/keys specs without correspondingly speccing the leaves as >> an "incrementally lock down/validate" approach, I wouldn't be too upset if >> I lost that ability and it started throwing an error. I mean it throws an >> error if I go to generate it anyway. >> >> On Friday, October 6, 2017 at 8:58:38 AM UTC-7, Leon Grapenthin wrote: >>> >>> Thanks, Beau. >>> >>> I am still interested why this default behavior has been chosen. It >>> doesn't seem like a reasonable trade-off at this point. >>> >>> It enables me to say: "The map must have this key", without specifying >>> how the data mapped to it will look like. >>> >>> If I ever wanted to do that, I could as well spec that key with "any?". >>> >>> What are other benefits? They must justify the expense of likely runtime >>> errors. >>> >>> >>> On Friday, October 6, 2017 at 5:34:16 PM UTC+2, Beau Fabry wrote: >>>> >>>> Leon, perhaps you could add this code to your test suite? >>>> >>>> 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 Friday, October 6, 2017 at 5:56:29 AM UTC-7, Leon Grapenthin wrote: >>>>> >>>>> Open maps/specs are fine. >>>>> >>>>> s/keys supporting unregistered specs are not. >>>>> >>>>> At least to me. I just fixed two more bugs in production that were >>>>> would not have happened. >>>>> >>>>> What are the supposed benefits of this feature? >>>>> >>>>> I can only infer "being able to require keys without their spec being >>>>> known" which is a usecase I had exactly 0.00% of the time so far. >>>>> >>>>> Anything I have missed? >>>>> >>>>> Kind regards, >>>>> Leon. >>>>> >>>>> >>>>> On Wednesday, October 4, 2017 at 7:05:29 PM UTC+2, Beau Fabry wrote: >>>>>> >>>>>> Seems like that's the reasonable place to check it, otherwise you're >>>>>> forced into an ordering for your specs and cannot write recursive strict >>>>>> map specs. >>>>>> >>>>>> On Wednesday, October 4, 2017 at 8:59:59 AM UTC-7, Yuri >>>>>> Govorushchenko wrote: >>>>>>> >>>>>>> Thanks. This approach is also different from the macro because it >>>>>>> will check specs existence at the validation time, not at the s/def >>>>>>> call. >>>>>>> >>>>>>> On Wednesday, October 4, 2017 at 4:18:16 PM UTC+3, Moritz Ulrich >>>>>>> wrote: >>>>>>>> >>>>>>>> Yuri Govorushchenko <yuri....@gmail.com> writes: >>>>>>>> >>>>>>>> > 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 >>>>>>>> >>>>>>>> Note that you can simply combine a custom predicate and `s/keys` in >>>>>>>> clojure.spec to verify that all keys in a given map have a >>>>>>>> underlying >>>>>>>> spec: >>>>>>>> >>>>>>>> ``` >>>>>>>> (s/def ::whatever (s/and (s/keys ...) >>>>>>>> #(every? keyword? (keys %)) >>>>>>>> #(every? (comp boolean s/get-spec) (keys >>>>>>>> %)) ) >>>>>>>> ``` >>>>>>>> >>>>>>> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > -- 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.