2014-11-04 4 views
5

Wenn ich versuche, den folgenden Code in meinem Emacs Cider-Repl abzuwerten, wird wie erwartet nil zurückgegeben, aber keiner der Ausdrucke findet im Repl-Puffer oder in der Konsole statt. Wie kann ich diesen Ausdruck wie gewünscht erstellen?Warum kann ich nicht aus Hintergrundthreads in Clojure Cider REPL in Emacs drucken?

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

Dies funktioniert gut, aber:

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

Antwort

10

Das Verhalten von println ist eine dynamisch gebundene var *out* als sein Ausgangsstrom genannt zu verwenden. emacs bindet *out* dynamisch an den repl-Puffer für im repl-Puffer ausgewerteten Code, aber wenn Sie einen Thread erstellen, erhält der Thread *out* die Root-Bindung von *out*, was im Fall von Apfelwein nicht der repl-Puffer sein wird.

Wenn Sie die repl mit cider-jack-in gestartet, wenn Sie auf Sie schauen Liste Puffer sollte ein Puffer mit einem Namen wie *nrepl-server* sein, die den Ausgang der Wurzel enthält *out* Bindung. Hier ist der Inhalt von mir nach dem Code ausgeführt wird:

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] 

Wenn Sie nicht cider-jack-in verwendet haben, wird die Ausgabe auf dem Terminal drucken, wo Sie den nrepl Prozess gestartet.

+0

Sie so viel Dank! Das löst das Geheimnis und du hast mir gerade etwas über Clojure und Emacs beigebracht.Gibt es eine Möglichkeit, die Variable * out * für Hintergrund-Threads neu zu binden, um sie auch im Repl-Puffer auszudrucken? – kurofune

+0

'* out *' kann mit 'binding' gesetzt werden, wie jede andere dynamische Variable auch. @ Amalloys Antwort macht einen guten Job, diesen Teil zu zeigen, denke ich. – noisesmith

+0

direkt an. Ihr beide habt das sehr klar für mich gelöst. Vielen Dank. – kurofune

9

*out* ist die dynamische Variable, die bestimmt, wo die Ausgabe von println und ähnlichen Funktionen geht. Es ist Thread-gebundene an irgendeinen Ort, der Sachen verursacht, die zu emacs für die Anzeige durch Apfelwein zurückgeschickt werden; wenn du einen neuen thread startest, ist diese bindung nicht vorhanden, und die ausgabe geht woanders hin (wahrscheinlich zum stdout des nrepl-servers emacs/leiningen, der im hintergrund gestartet wurde).

Sie können dies auf verschiedene Arten beheben. Sie können den Wert von *out* aus dem übergeordneten Thread erfassen und sie dann in einem Verschluss zusammen mit dem Kind Faden passieren, und rebind *out* es:

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

Oder Sie können sich selbst ein future anstelle des Startens des Themas verwenden : Clojure übermittelt automatisch relevante thread-lokale Bindungen an neue Threads, die für eine Zukunft gestartet wurden.

+0

Hey Mann, könntest du mir ein Codebeispiel mit Zukunft zeigen? Ich habe im RepL damit herumgespielt, aber ich konnte es nicht genau herausfinden. – kurofune

0

Wenn Sie Figwheel verwenden, dann PRN tun/println in Ringhandlern (die dem oben gezeigten Threads-Beispiel tatsächlich ähnlich sind) können auch von Fingerleel selbst verschluckt werden. Überprüfen Sie das Projekt.clj Ihres Projekts (suchen Sie nach dem Schlüssel: server-logfile in der: figwheel map), wo Sie kontrollieren können, ob aus zum repl oder zu einer Logdatei gehen soll. Bitte beachten Sie, dass dies nur dann gilt, wenn Sie figwheel verwenden, ansonsten funktioniert das Drucken auf die REPL natürlich einwandfrei.

Siehe meine Antwort auf diese Frage für weitere Informationen: Output compojure server print statements into figwheel terminal?

Verwandte Themen