6

当我在 emacs 中从 Swank repl 运行 Clojure 代码时,主线程将使用 printf 将消息打印到 repl。但是,如果我运行代理或显式创建也打印的其他线程,有时输出不会显示,有时它会显示在我正在运行 Swank 的控制台窗口中。我很想知道为什么。

编辑:感谢丹尼尔在下面的回答,我现在知道其他线程没有绑定到 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)))))))
4

2 回答 2

1

原因是,在其他线程*out*中没有绑定到 REPL 的流。尝试这样的事情:

(let [repl-out *out*]
  (defn foo []
    (binding [*out* repl-out]
      ...)))

现在,当foo从另一个线程运行时,*out*将绑定到您定义函数时的任何内容(即 SLIME REPL),因此打印将按预期工作。

或者,为了测试:

(defmacro future-output [& body]
  `(let [out# *out*]
     (future
       (binding [*out* out#]
         ~@body))))

注意:这是未经测试的,因为我在 atm 没有工作 Clojure/SLIME,但该代码在几个月前工作。Clojure 的较新版本(1.3 Alpha 2)可能存在差异:

  • 对于常见情况,使用 vars 的代码路径现在 快得多,您必须明确要求 :dynamic 可绑定性
于 2010-12-26T12:21:05.007 回答
0

如果您在使用 cake 时遇到同样的问题,那么在您的项目根目录(project.clj 所在的位置)的 .cake/cake.log 文件中应该有一个带有输出的日志文件。

于 2011-01-31T11:53:03.147 回答