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.

Reply via email to