On Wednesday, February 1, 2017 at 6:12:35 PM UTC-6, Dave Tenny wrote:
>
> Looking at the documentation for keywords under 
> https://clojure.org/reference/reader#_literals
> there is no mention for the syntax for namespace aliased keywords, and 
> this is very important it you want to manage your keywords for clojure.spec.
>

Agreed! This is definitely under doc'ed. I've added an issue to the site 
repo and I will work on that. Track 
at https://github.com/clojure/clojure-site/issues/164

I do want to clarify some terms. Keywords start with a ":". Auto-resolved 
keywords start with a "::". Generally, I prefer saying a keyword is 
"qualified" when has a namespace part. There is an unfortunate overlap in 
terms here where the namespace part of a keyword may or may not refer to an 
actual Clojure namespace, so it can be confusing to use the word 
"namespace" in this context (as it might imply more than it should). So I 
would say your question is really primarily about qualified auto-resolved 
keywords.
 

> I only know about it because google turned up some clojure.spec notes on 
> it, but it seems it should be in the mainline clojure docs too.
> I certainly didn't know about it until today.
>

Auto-resolved and qualified auto-resolved keywords have been part of 
Clojure since very early days (pre 1.0 I believe) and have not really 
changed much if at all since then. 
 

> Say we have this namespace:
>
> (ns foo 
>   (:require [clojure.spec :as s]))
> (s/def ::specific-even-number #(= 1000 %))
>
>
>
>
> And then in the user namespace:
>
> (ns user)
> (require '[clojure.spec :as s])
> (require '[foo :as f])
>
>
> (s/valid? :f/specific-even-number 1000) 
> ;; Exception Unable to resolve spec: :f/specific-even-number  clojure.spec
> /reg-resolve! (spec.clj:70)
>
> What is needed is the extra colon, as if we're saying use the current 
> namespace, only that isn't what happens.
> (s/valid? ::f/specific-even-number 1000)
> ;; true
>
 
You also could have done (which is just what the above resolves to):

   (s/valid? :foo/specific-even-number 1000)

There are two (or maybe three depending how you look at it) kinds of 
auto-resolved keywords:

1) Unqualified (or simple) auto-resolved keywords like "::foo". These 
keywords are automatically resolved using the current *ns* into a qualified 
keyword, such as :user/foo (note that context matters).
2) Qualified auto-resolved keywords like "::a/foo". In this case the 
qualifier ("a") is resolved in terms of the namespace mappings of the 
current *ns*, so "a" will resolve to whatever "a" is aliasing (or an error 
if it is not a valid alias).
3) Kind of a special case of #2 is that qualifiers that are actual 
namespaces will also resolve in keywords like "::clojure.string/foo" which 
will resolve to ":clojure.string/foo". This is kind of weird and not 
something people typically do intentionally (so I'd recommend against it).

Perhaps the clojure docs are correctly stating the use of this kind of 
> keyword my interpretation is just flawed, but it certainly wasn't obvious 
> to me, and nobody in my team knew that we could do this either.  The result 
> was some namespace unfriendly code to avoid typing in long namespaces on 
> clojure spec keywords.  Now that we know ::ns-alias/keyword we can do 
> better on our clojure.spec use.
>
> (The above tested in clojure 1.8.0).
>
> While I'm here, I want to say that I am _deeply_ disappointed that 
> clojure.spec def/fdef forms don't support documentation strings.  I upvoted 
> the issue in the bug tracker, but there were only 27 votes including mine 
> when I checked on this half-year-plus old issue.
> http://dev.clojure.org/jira/browse/CLJ-1965
>

Well, no reason to be disappointed yet - spec is still a work in progress. 
That's actually one of the top voted issues in the whole system so I am 
well aware of it. I share the desire to see docstrings for specs (which we 
could leverage in "doc" - btw, you can (doc :foo/specific-even-number) now) 
and it's something Rich suggested to me in the early days of spec. The big 
question is how to implement it. There is not currently a good place to 
stash it so it just needs some analysis. It also opens up questions about 
other meta for specs (like we currently have some file/attributes in some 
cases that could be used to make "source" work with it - that would be 
handy if it always worked).

I also have to wonder why keyword namespaces aren't processed like other 
> symbol namespaces, that is, to interpret the namespace portion before a '/' 
> with alias consideration.
> No doubt there's a good answer, but it seems anachronistic that keywords 
> need special syntax contortions to recognize namespace aliases when other 
> symbols do not.
> (Yes, clojure keywords may not be thought of as symbols, still, the rules 
> for alias recognition are inconsistent).


Regular keyword namespaces *are* processed like symbol namespaces and this 
(importantly) makes them _values_ that can be understood unambiguously 
independent of their processing context. Auto-resolved keywords are special 
in that the reader (which otherwise has very few ties to the outer 
environment) must reach into your current *ns* to understand how to 
auto-resolve the qualifier.

Note that because they depend on environment context during reading, 
auto-resolved keywords are NOT part of the edn spec and are not supported 
by the edn reader. This is a good example of why they are somewhat special.

I also would like to mention that there were two syntax enhancements made 
in Clojure 1.9 related to easing the use of qualified keywords:

- Map namespace literal syntax - a convenience for specifying the qualifier 
of all keyword/symbol keys for a map once, rather than once per key. The 
syntax here echoes the auto-resolved keyword syntax. See docs 
at: https://clojure.org/reference/reader#_maps
- Qualified key destructuring which similarly allows you to destructure a 
set of keys with the same qualifier and specify the qualifier once rather 
than once per key. See docs 
at: https://clojure.org/reference/special_forms#_map_binding_destructuring

-- 
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