When I run Clojure code from the Swank repl in emacs, the main thread will print out messages using printf to the repl. But if I run agents or explicitly create other threads which also print, sometimes the output doesn't show up, and other times it shows up in the console window where I'm running Swank. I'd love to understand why.
Edit: Thanks to Daniel's answer below I now know that the other threads do not have out bound to the output of the REPL. This code works because you pass in the out from where you run from. However my new problem is that this code now blocks per thread so rather than running in parallel it runs each thread one at a time, so I need a more thread aware output method.
(defn sleeper-thread [out id t]
"Sleep for time T ms"
(binding [*out* out]
(printf "%d sleeping for time %d\n" id t)
(Thread/sleep t)
(printf "%d slept\n" id)))
(defn test-threads [n out]
(dotimes [x n]
(.start (Thread. (#(sleeper-thread %1 %2 %3) out x (+ 2000 (rand-int 5000)))))))
The reason is, that in other threads *out*
is not bound to the REPL's stream. Try something like this:
(let [repl-out *out*]
(defn foo []
(binding [*out* repl-out]
...)))
Now, when running foo
from another thread, *out*
will be bound to whatever it was when you defined the function (i.e. the SLIME REPL), so printing will work as expected.
Or, for testing:
(defmacro future-output [& body]
`(let [out# *out*]
(future
(binding [*out* out#]
~@body))))
Note: This is untested, because I have no working Clojure/SLIME here atm, but that code worked a few months ago. There might be differences in newer Versions of Clojure (1.3 Alpha 2):
- code path for using vars is now much faster for the common case, and you must explicitly ask for :dynamic bindability
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With