In terms of code loading, acyclic dependencies turned out to be a great design choice in Clojure - why its benefits shouldn't apply to or be justified for spec loading is totally unclear to me.
To make my point more clear let me recap. I am simply asking for s/keys to throw if provided specs aren't registered. Because my colleagues and I myself made costly mistakes that would have been prevented. The most common scenario is a typo like the one I have illustrated above. I have asked what benefits justify current behavior? The only justification comes from Sean saying that it helps him prototyping. While I agree I also observe that this is simultaneously the trapdoor leading to such silently passing specs. And why prototyping needs should not be a primary concern in how s/keys behaves. I have tried to make a case for current behavior: It allows to say a key is there, without saying anything about its value. I have pointed out (s. a.) why this IMO has too little utility to justify anything. Regarding Clojure being a dynamic lanugage this doesn't really make a difference here: There is not much dynamic going on about registration and spec in general. Registration etc. is evaluated at compile time. Note that s/def, s/keys etc. are all macros whose expansion is evaluated at compile time. On Monday, October 9, 2017 at 7:20:42 PM UTC+2, Beau Fabry 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. > > 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? > > > 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.