On Apr 30, 2009, at 9:43 AM, Julien wrote:

-here's the clojure code:


(def text1 "testing thread")
(def T (proxy [Thread] []
         (run []
              (println "T thread : (eval (println text1))")
              (eval (println text1))

(println "T thread : (eval (read-string \"(println text1)\"))")
              (eval (read-string "(println text1)"))
              )))

(println "Main thread : (eval (println text1))")
(eval (println text1))
(println "Main thread : (eval (read-string \"(println text1)\"))")
(eval (read-string "(println text1)"))
(. T start)

At any given time, within any given thread, the "current namespace" is bound to the var *ns*, a dynamic variable. Every thread has (potentially) an independent value for *ns*. If no call to "bind" has been made since the thread started, *ns* within that thread will be bound to its root binding which is the clojure.core namespace:

        user=> (.getRoot (var *ns*))
        #<Namespace clojure.core>

Within the body of T:


- In the first eval, the expression (println text1) was compiled in the main thread while the user namespace was current. text1 was resolved at compile time to become user/text1.

The entire expression was resolved like this:

        user=> `(eval (println text1))
        (clojure.core/eval (clojure.core/println user/text1))

and the compiled.

When T ran, the current namespace was clojure.core, but the reference to text1 was fully qualified and referenced the intended var in user. Note that in this case "(clojure.core/println user/text1)" ran to completion while it was being evaluated as an argument to eval. What eval actually received was "nil". eval of nil produced nil.


- In the second eval, read-string produced a data structure that was passed to eval. eval tried to do its work by compiling the expression and running it. That compilation occurred within thread T where the current namespace was clojure.core. Since clojure.core/text1 doesn't exist, text1 could not be resolved and the compiler threw an exception.

You can "fix" the second eval either by changing \"(println text1)\" to \"(println user/text1)\" or by surrounding the body of T with a "binding" call that binds *ns* to user, or binds it to any namespace and then sets it with a call to "(in-ns 'user)".

--Steve

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to