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.


Reply via email to