使用 swank/slime 了解 Clojure 中的输出
当我从 emacs 中的 Swank repl 运行 Clojure 代码时,主线程将使用 printf 将消息打印到 repl。但是,如果我运行代理或显式创建其他也打印的线程,有时输出不会显示,而其他时候它会显示在我运行 Swank 的控制台窗口中。我很想了解为什么。
编辑:感谢 Daniel 在下面的回答,我现在知道其他线程没有 out 绑定到 REPL 的输出。此代码之所以有效,是因为您从运行位置传入out。然而我的新问题是,这段代码现在会阻塞每个线程,因此它不是并行运行,而是一次运行每个线程,所以我需要一种更多线程感知的输出方法。
(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)))))))
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)))))))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
原因是,在其他线程中
*out*
未绑定到 REPL 的流。尝试这样的事情:现在,当从另一个线程运行
foo
时,*out*
将绑定到您定义函数时的任何内容(即 SLIME REPL),因此打印将按预期进行。或者,用于测试:
注意:这是未经测试的,因为我这里没有可用的 Clojure/SLIME atm,但该代码在几个月前就可以工作。 新版 Clojure (1.3 Alpha 2) 中可能存在差异:
The reason is, that in other threads
*out*
is not bound to the REPL's stream. Try something like this: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:
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):
如果您在使用 cake 时遇到同样的问题,则项目根目录(project.clj 所在的位置)中的 .cake/cake.log 文件中应该有一个包含输出的日志文件。
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).