Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';我不能在emacs中的Clojure苹果汁REPL中从背景线程打印吗?_Emacs_Clojure_Stdout_Read Eval Print Loop_Cider - Fatal编程技术网

为什么可以';我不能在emacs中的Clojure苹果汁REPL中从背景线程打印吗?

为什么可以';我不能在emacs中的Clojure苹果汁REPL中从背景线程打印吗?,emacs,clojure,stdout,read-eval-print-loop,cider,Emacs,Clojure,Stdout,Read Eval Print Loop,Cider,如果我尝试在emacs苹果酒repl中计算以下代码,则会像预期的那样返回nil,但所有打印都不会在repl缓冲区或控制台中进行。我怎样才能按预期打印出来 (dotimes [i 5] (.start

如果我尝试在emacs苹果酒repl中计算以下代码,则会像预期的那样返回nil,但所有打印都不会在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

println
的行为是使用名为
*out*
的动态绑定变量作为其输出流。emacs动态绑定
*out*
以转到repl缓冲区,以获取在repl缓冲区中计算的代码,但是如果创建线程,该线程的
*out*
将获得
*out*
的根绑定,在苹果酒的情况下,该根绑定将不是repl缓冲区

如果您使用苹果汁插口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]

如果未使用苹果酒插口in,则输出将打印到启动nrepl过程的终端。

*out*
是动态变量,用于确定从
println
和类似函数输出的位置。它被线程绑定到某个地方,导致将内容发送回emacs以通过苹果酒显示;如果启动一个新线程,则该绑定将不存在,并且输出将转到其他位置(可能是在后台启动的nrepl服务器emacs/leiningen的标准输出)

你可以用几种方法来解决这个问题。您可以从父线程捕获
*out*
的值,然后在闭包中将其传递给子线程,然后重新绑定
*out*

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

或者您可以使用
future
而不是自己启动线程:Clojure会自动将相关线程本地绑定传送到为将来启动的新线程。

在repl中执行以下表达式,然后所有输出都将在repl中结束:

(alter-var-root #'*out* (constantly *out*))
原始答复:


如果您使用的是Figwheel,那么在ring处理程序中执行prn/println(实际上与上面所示的线程示例类似)也可能会被Figwheel本身吞并。检查项目的project.clj(在:figwheel映射中查找key:server日志文件),在那里可以控制out是应该转到repl还是转到日志文件。请注意,这仅适用于使用figwheel的情况,否则打印到REPL当然可以正常工作


有关更多详细信息,请参见我对这个问题的回答:

非常感谢!这就解开了谜团,你刚刚教了我一些关于Clojure和Emacs的知识。是否有某种方法可以为后台线程重新绑定out变量,以便也将out打印到repl缓冲区?
*out*
可以使用
绑定设置,就像任何其他动态变量一样@amalloy的回答很好地展示了我认为的这一部分。嘿,伙计,你能给我展示一个使用future的代码示例吗?我在repl上玩过它,但我不太明白。(未来(println“test”))