On Fri Mar 18 15:53 2011, Nathan Sorenson wrote:
> I want to examine the namespace within a swing thread, as I want to
> see if a particular var is defined from another part of the program
> before operating on it. However, inside the "do-swing" macro (or just
> using SwingUtilities/invokeLater directly) *ns* will always refer to
> clojure.core, not the namespace of the file I'm working on.
> 
> eg:
> 
> (ns some-namespace)
> (javax.swing.SwingUtilities/invokeLater (fn [] (println *ns*)))
> 
> will print:
> #<Namespace clojure.core>
> 
> But if I'm defensive and copy *ns*:
> 
> (ns other-namespace)
> (def this-namespace *ns*)
> (javax.swing.SwingUtilities/invokeLater (fn [] (println this-
> namespace)))
> 
> will print:
> #<Namespace other-namespace>
> as expected.


I believe this is the expected behaviour.  Recall that the purpose of
invokeLater is to run the given code in the UI rhread, which is often
different from the thread in which the REPL (or more generally, your
program) is runing.  As such, an thread-specific bindings like *ns*
will, when dereferenced, use the thread-local bindings in the Swing
thread.

If you want to preserve the bindings from the caller's context, you can
use the bound-fn macro:

user=> (javax.swing.SwingUtilities/invokeLater (bound-fn [] (println *ns*)))
nil
user=> #<Namespace user>

> Interestingly, all DEF instructions are interned into the expected
> namespaces:
> 
> other-namespace> (javax.swing.SwingUtilities/invokeLater (fn [] (def
> somevar 1)))
> nil
> other-namespace> somevar
> 1
> other-namespace> clojure.core/somevar
> ; Evaluation aborted.
> other-namespace> other-namespace/somevar
> 1
> 
> 
> Is this expected behaviour?

I haven't looked at the code to check whether this is the case, but I am
assuming that def being a special form is causing the compiler to make
sure to namespace-qualify the deffed var at compile-time, rather than at
run-time.

Sincerely,

Daniel Solano Gómez

Attachment: pgpUFwSk9DJkl.pgp
Description: PGP signature

Reply via email to