Here's another mental model that you can use. (Not sure it is 100% accurate with the actual implementation, but it has served me well so far.)
Keywords are not bound, in the same sense that numbers are not bound. 1 is 1, just as 2 is 2, whatever the namespace you are into. 1 from the user namespace is the same a 1 from the clojure.core namespace. Similarly, the keyword :hello is not bound, it just is. :hello in the user namespace is the same value as :hello in the core namespace or in any other namespace. As keywords are very lightweight to create and very fast to compare for equality, they are often used as keys in associative data structures. Sometimes, though, you actually want to have keywords that are local to your namespace, because you want to encapsulate some behaviour. Say you want to create a simple tree-manipulation library, where your nodes are, for some reason, represented as maps with a special key :children. Other than that, you want the user of your library to be able to add any information to the maps representing the nodes of the tree. One way to approach this would be to document that the special key :children is reserved and cannot be used. Another way to handle this would be to create a keyword that is supposedly unique to your library, by prefixing the keyword with some chosen prefix, say :tree-children. That would soon become quite cumbersome to type, and does not really preclude the preceding point, though it would make conflicts rarer. But there is one thing that Clojure can guarantee, which is that in a single application, there will not be two namespaces with the same name. So, assuming your library is contained in a namespace called my.tree-manipulation.core, you could decide to call your special key :my.tree-manipulation.core.children. That, too, would be cumbersome, but conceivably safer. Now, this is originally an implementation detail, but it just so happens that keywords are basically implemented as symbols that evaluate to themselves. That is, if keywords did not exist in Clojure, you could "invent" them by declaring them as (def :a ':a); after that declaration, :a would work exactly like a keyword works today in Clojure. Which means that we can reuse the namespace resolution feature of symbols : every time the reader reads in a symbols, it first resolves it in the current namespace, and then evaluates the full symbol to find its value. Keywords sort of short-circuit that by default. However, with the :: notation, you are basically telling the reader to first evaluate the given symbol in the current namespace, then evaluate it as a symbol. So ::bla in namespace test is the same as typing the full keyword :test/bla. But the keyword itself is not resolved in the namespace, the keyword just is. It just so happens that its value looks like a namespace-qualified symbol with a colon in front. Getting back to the tree example, you can thus have your special key be ::children, which combines the two following advantages : the actual keyword is pretty specific to your library, as the real keyword seen by the compiler will be :my.tree-manipulation.core/children, but it is also nearly as short to type and to read as plain :children. Now let's look at your questions in light of this mental model. On 9 March 2013 19:37, nick rothwell <n...@cassiel.com> wrote: > I understand that ::foo is a keyword bound into the local namespace. So ::foo is actually a shorthand for the :my.ns/foo keyword, which is a value by itself, independently of any enclosing or existing namespace. (Keywords follow the symbol rule of "maximum one / in the name", but there is actually no link with existing namespaces : you can use a keyword :no-namespace/k even if there is no namespace called no-namespace.) > I also understand (according to the docs) that > > :my.namespace/foo is the keyword foo in the namespace my.namespace. As I stated earlier, namespaces are only of interest to symbol resolution; they do not interfere with keywords beyond their optional construction via the :: shorthand. > ::nsalias/foo is the keyword foo in the namespace my.namespace if I've > aliased my.namespace to nsalias. So Clojure first tries to find the corresponding symbol, then only converts it to a keyword. Thus namespace resolution works with aliases. The resulting keyword is still a value by itself. > But also: > > ::my.namespace/foo is equivalent to :my.namespace/foo (as a convenience, I > guess). Resolving an already namespace-qualified symbol yields the same namespace-qualified symbol. > :nsalias/foo is not the same as ::nsalias/foo - in fact, I'm not sure what > :nsalias/foo is - a call on str yields ":nsalias/foo". :nsalias/foo is the value :nsalias/foo - symbols are self-evaluating values, just as 1 is 1. The fact that it looks like a namespaced symbol is irrelevant. ::nsalias/foo is asking the reader to first resolve the symbol nsalias/foo in the current namespace, using known aliases if need be, and only afterwards turning it into a keyword. So :existing-namespace/k is the same as ::existing-namespace/k, but :alias/k is not the same as ::alias/k. > This last point is the one that's confusing me. Hope I've been able to shed some light. -- -- 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/groups/opt_out.