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

If I try to evaluate the following code in my emacs cider-repl, nil is returned, as expected, but no printing is done in the replix buffer or console. How can I make this listing as intended?

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

This works great, however:

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

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

If you started the replica using cider-jack-in , when viewing the buffer list, there should be a buffer with a name of the type *nrepl-server* , which contains the output of the root binding *out* . Here is my content 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 be printed to the terminal where you started the nrepl process.

+10
source

*out* is a dynamic variable that determines where the output from println and similar functions comes from. It is tied to a thread somewhere, which causes the material to send emacs back to display cider; if you start a new thread, this binding is absent, and the output goes elsewhere (perhaps in the stdout of the nrepl server emacs / leiningen is started in the background).

You can solve this in several ways. You can write the value *out* from the parent stream, and then pass it to the child stream in closing and reload *out* to it:

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

Or you can use the future instead of starting the thread itself: Clojure automatically passes the corresponding streaming local bindings to new threads launched in the future.

+9
source

Run the following expression in repl, then all the output will be in repl:

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

original answer:

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

+5
source

If you use Figwheel, then running prn / println in call handlers (which are actually similar to the Threads example shown above) can also be swallowed by Fighweel itself. Check the project.clj project (find the key: server-logfile inside: figwheel map), where you can control if the output should go to repl or to the log file. Please note that this only applies if you are using figwheel, otherwise printing on REPL is certainly fine.

See my answer on this question for more details: Outputting compojure server print reports to figpheel terminal?

0
source

Source: https://habr.com/ru/post/1206193/


All Articles