surprising behaviour with do, ns and def

4 views
Skip to first unread message

Chris Kent

unread,
Jul 13, 2009, 3:58:31 PM7/13/09
to Clojure
I've noticed that changing namespace with ns and then doing a def
doesn't behave the same inside a do form:

Without the do form it works as expected:

user=> (ns a) (def foo "foo")
nil
a=> #'a/foo
a=>

If the same code is executed inside a do form the var is defined in
the original namespace. I thought that the do should make no
difference. Is this the intended behaviour?

user=> (do (ns a) (def foo "foo"))
#'user/foo
a=>

Thanks
Chris

Stuart Sierra

unread,
Jul 13, 2009, 10:04:10 PM7/13/09
to Clojure
On Jul 13, 3:58 pm, Chris Kent <cjk...@gmail.com> wrote:
> user=> (ns a) (def foo "foo")
> a=> #'a/foo
> a=>
>
> If the same code is executed inside a do form the var is defined in
> the original namespace.  I thought that the do should make no
> difference.  Is this the intended behaviour?
>
> user=> (do (ns a) (def foo "foo"))
> #'user/foo
> a=>


Hi Chris,

This involves some subtle details of how the Clojure Reader works, but
I'll try to explain what's going on.

In your first example, the Reader reads the (ns...) form first, then
evaluates it, which sets the current namespace to "a". Then the
Reader reads the (def...) form, while it is in namespace "a". So, to
emphasize, we are in namespace "a" when the (def...) form is READ.

In your second example, the Reader reads the entire (do...) form
before anything gets evaluated. At that time, we are still in the
"user" namespace. So the (def...) form gets READ in namespace "user".

The crux is this: (def...) is a special form, so the usual rules don't
apply. In this case, what matters is when the (def...) form gets
READ, not when it gets evaluated. To get the behavior you expect, try
the "intern" function.

-Stuart Sierra

Chris Kent

unread,
Jul 14, 2009, 2:13:37 PM7/14/09
to Clojure
Hi Stuart

Thanks for the explanation, that makes sense and I very much doubt I'd
have figured that out by myself without a lot of head scratching. And
you were right about the intern function, that does exactly what I was
looking for.

Cheers
Chris
Reply all
Reply to author
Forward
0 new messages