2014-11-04 21 views
5

如果我嘗試在emacs cider-repl中評估以下代碼,則按預期方式返回nil,但打印不會發生在repl緩衝區或控制檯中。我如何按預期打印此打印件?爲什麼我不能從Emacs的Clojure Cider REPL的後臺線程打印?

(dotimes [i 5]                                   
    (.start                                    
    (Thread.                                   
    (fn []                                    
     (Thread/sleep (rand 500))                              
     (println (format "Finished %d on %s" i (Thread/currentThread))))))) 
;=> nil 

這工作得很好,但是:

(println (format "Finished 1 on %s" (Thread/currentThread))) 
;=> Finished 1 on Thread[nREPL-worker-18,5,main] 
----------- mini-buffer ----------------- 
nil 

回答

10

println的行爲是使用一個動態綁定的VAR稱爲*out*作爲其輸出流。 emacs動態綁定*out*以轉到repl緩衝區以查看repl緩衝區中計算的代碼,但是如果創建線程,則該線程的*out*將獲得*out*的根綁定,這在蘋果酒的情況下不會是repl緩衝區。

如果您使用cider-jack-in開始repl,當您查看緩衝區列表時,應該有一個名爲*nrepl-server*的緩衝區,其中包含根*out*綁定的輸出。這裏是我的內容運行代碼後:

nREPL server started on port 52034 on host 127.0.0.1 - nrepl://127.0.0.1:52034 
Finished 1 on Thread[Thread-9,5,main] 
Finished 0 on Thread[Thread-8,5,main] 
Finished 2 on Thread[Thread-10,5,main] 
Finished 3 on Thread[Thread-11,5,main] 
Finished 4 on Thread[Thread-12,5,main] 

如果你沒有使用cider-jack-in,輸出將打印到您開始nrepl處理終端。

+0

非常感謝!這解決了這個謎,你只是教了我一些關於Clojure和Emacs的東西。有什麼辦法可以重新綁定後臺線程的* out *變量來打印出repl緩衝區嗎? – kurofune 2014-11-04 20:16:44

+0

'* out *'可以使用'binding'來設置,就像任何其他的動態變量一樣。 @ amalloy的答案在展示我認爲的那部分方面做得很好。 – noisesmith 2014-11-04 20:29:25

+0

對。你們倆都很清楚地解決了我的問題。謝謝。 – kurofune 2014-11-04 20:35:03

9

*out*是確定println和類似功能的輸出所在的動態變量。這是線程綁定到某個地方,導致東西被髮回emacs供蘋果酒顯示;如果你啓動一個新的線程,那個綁定不存在,並且輸出到別處(可能是在後臺啓動的nrepl服務器emacs/leiningen的stdout)。

您可以通過幾種方式解決這個問題。你可以捕捉*out*從父線程的值,然後把它傳遞到一個封閉的子線程,並重新綁定*out*它:

(let [out *out*] 
    (.start (Thread. (fn [] 
        (binding [*out* out] 
         (println "test")))))) 

或者你可以使用一個future,而不是自己啓動線程:Clojure自動將相關的線程本地綁定傳送給爲將來啓動的新線程。

+0

嘿,你能告訴我一個使用未來的代碼示例嗎?我在repl玩過它,但我無法弄清楚。 – kurofune 2014-11-06 19:39:23

0

如果使用Figwheel,然後做PRN/ringl處理程序中的println(實際上類似於上面顯示的Threads示例)也可以被Fighweel本身吞噬。檢查項目的project.clj(查找:figwheel映射中的關鍵字:server-logfile),您可以在其中控制out應該轉到repl還是轉到日誌文件。請注意,這僅適用於使用花輪,否則打印到REPL當然可以正常工作。

看到我對此問題的回答獲取更多詳情:Output compojure server print statements into figwheel terminal?

相關問題