开发者

Understanding output in Clojure using swank/slime

开发者 https://www.devze.com 2023-02-01 00:12 出处:网络
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 oth开发者_如何转开发er threads which al

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 oth开发者_如何转开发er 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 are struggling with the same using cake, there should be a log file with the output in the .cake/cake.log file in your project root (where project.clj lives).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号