Why can't I print from background threads in Clojure Cider REPL in emacs?

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-27 02:00:10

问题


If I try to evaluate the following code in my emacs cider-repl, nil is returned, as expected, but none of the printing takes place in the repl buffer or console. How can I make this print out as intended?

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

This works fine, however:

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

回答1:


The behavior of println is to use a dynamically bound var called *out* as its output stream. emacs dynamically binds *out* to go to the repl buffer for code evaluated in the repl buffer, but if you create a thread, that thread's *out* gets the root binding of *out*, which in the case of cider will not be the repl buffer.

If you started the repl using cider-jack-in, when you look at you buffer list there should be a buffer with a name like *nrepl-server* which contains the output of the root *out* binding. Here is the contents of mine after running your code:

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]

If you did not use cider-jack-in, the output will print to the terminal where you started the nrepl process.




回答2:


*out* is the dynamic variable determining where output from println and similar functions goes. It is thread-bound to someplace that causes stuff to be sent back to emacs for display by cider; if you start a new thread, that binding is not present, and the output goes elsewhere (probably to the stdout of the nrepl server emacs/leiningen started in the background).

You can address this in a few ways. You could capture the value of *out* from the parent thread, and then pass it along to the child thread in a closure, and rebind *out* to it:

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

Or you can use a future instead of starting the thread yourself: Clojure automatically conveys relevant thread-local bindings to new threads started for a future.




回答3:


Execute the following expression in the repl, then all output will end up in the repl:

(alter-var-root #'*out* (constantly *out*))

original answer:

https://groups.google.com/d/msg/cider-emacs/bIVBvRnGO-U/nDszDbGoVzgJ




回答4:


If you are using Figwheel, then doing prn/println in ring handlers (which are actually similar to the Threads example shown above) can also be swallowed by Fighweel itself. Check your project's project.clj (look for the key :server-logfile inside the :figwheel map), where you can control if out should go to the repl or to a logfile. Please note, this only applies if you are using figwheel, otherwise the printing to the REPL of course works fine.

See my answer on this question for more details: Output compojure server print statements into figwheel terminal?



来源:https://stackoverflow.com/questions/26743958/why-cant-i-print-from-background-threads-in-clojure-cider-repl-in-emacs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!