Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding output in Clojure using swank/slime

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)))))))
like image 408
justinhj Avatar asked Dec 26 '10 05:12

justinhj


1 Answers

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
like image 121
danlei Avatar answered Oct 17 '22 19:10

danlei