>
> One way to prevent that would be to only ever use aliases for fully 
> qualified keywords, never type out the whole thing.
>

Uh, you forced me to go learn more about keywords. I didn't know you could 
do ::namespace/name to alias keywords.

I've been manually namespacing my keywords until now, which was tedious and 
error prone. Also, because I was doing it manually, I made my namespace 
real short, as its annoying to have to type :com.company.project.wtv/name 
everywhere.

Thanks for the tip.

I do feel that for this though, it asks for a bit too much discipline on 
the programmer, and in this case, also a good amount of knowledge around 
spec and keywords, so I might still use the macro, but also switch to 
aliased keywords.

On Friday, 10 November 2017 10:07:52 UTC-8, Beau Fabry wrote:
>
> One way to prevent that would be to only ever use aliases for fully 
> qualified keywords, never type out the whole thing. 
>
> On Thursday, November 9, 2017 at 11:22:24 PM UTC-8, Didier wrote:
>>
>> I just stumbled upon another potential mistake here. When you have specs 
>> split across namespaces. Its possible for a map spec in one namespace to 
>> have one of its key's use a spec from another namespace. If you forget to 
>> require that other namespace though, you won't know, and your map will 
>> always validate.
>>
>> (s/def ::spec (s/keys :req [:other/spec]))
>>
>> If :other/spec is not registered, ::spec still will succeed at being 
>> registered. And then, assuming :other/spec is defined as:
>>
>> (s/def :other/spec int?)
>>
>> I wouldn't matter, since:
>>
>> (s/valid? ::spec {:other/spec "123"})
>>
>> Will return true.
>>
>> But if you register :other/spec, it would return false.
>>
>> Normally, this has not been an issue for me, but now that I share my 
>> specs more, I've got specs in different namespace using one another, and 
>> I've already made this mistakes a few time, causing validation I thought 
>> was there to protect me, to actually be missing.
>>
>> So I made my own keys macro:
>>
>> (defmacro known-keys
>>   [& {:keys [req req-un opt opt-un gen] :as args}]
>>   (letfn [(known-spec? [k] (boolean (s/get-spec k)))]
>>     (doseq [e (concat req req-un opt opt-un)]
>>       (when (not (known-spec? e))
>>         (throw (ex-info (str e " is not a currently registered spec.") 
>> args)))))
>>   `(s/keys ~@(interleave (keys args) (vals args))))
>>
>> Which first checks that all keys are currently registered, and if so, it 
>> delegates back to s/keys. Otherwise it throws an exception at macro 
>> expansion time.
>>
>> I think this would also solve OPs problem, since it would throw if typos 
>> are made also.
>>
>> On Saturday, 14 October 2017 04:45:47 UTC-7, stuart....@gmail.com wrote:
>>>
>>> Hi Leon,
>>>
>>> I think it would be a mistake to introduce temporal coupling to prevent 
>>> typos. Here is an alternative that lets you identify "missing" keys specs at
>>> the time and place of your choosing, and then handle them as you deem 
>>> appropriate, without imposing those decisions on other users of spec:
>>>
>>> https://gist.github.com/stuarthalloway/f4c4297d344651c99827769e1c3d34e9
>>>
>>> Regards,
>>> Stu
>>>
>>>
>>>
>>>
>>> On Tue, Oct 10, 2017 at 12:33 PM, Leon Grapenthin <grapent...@gmail.com> 
>>> wrote:
>>>
>>>> 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 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