为什么我不能在emacs中的Clojure Cider REPL中从后台线程打印?

 不可能爱你啊 发布于 2022-12-13 10:04

如果我尝试在emacs cider-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

noisesmith.. 11

行为println是使用动态绑定的var *out*作为其输出流.emacs动态绑定*out*到repl缓冲区以获取在repl缓冲区中评估的代码,但是如果你创建一个线程,那个线程将*out*获得根绑定*out*,在cider的情况下,它不会是repl缓冲区.

如果你开始使用repl cider-jack-in,当你查看缓冲区列表时,应该有一个名称的缓冲区,*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进程的终端.

3 个回答
  • 行为println是使用动态绑定的var *out*作为其输出流.emacs动态绑定*out*到repl缓冲区以获取在repl缓冲区中评估的代码,但是如果你创建一个线程,那个线程将*out*获得根绑定*out*,在cider的情况下,它不会是repl缓冲区.

    如果你开始使用repl cider-jack-in,当你查看缓冲区列表时,应该有一个名称的缓冲区,*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进程的终端.

    2022-12-13 10:05 回答
  • 在repl中执行以下表达式,然后所有输出将以repl结尾:

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

    原始答案:

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

    2022-12-13 10:05 回答
  • *out*是确定来自println和类似函数的输出的动态变量.它被线程绑定到某个地方,导致东西被发送回emacs以供苹果酒显示; 如果你启动一个新线程,那个绑定不存在,输出转到别处(可能是在后台启动的nrepl服务器emacs/leiningen的stdout).

    您可以通过几种方式解决此问题.您可以*out*从父线程捕获值,然后将其传递给闭包中的子线程,并重新绑定*out*到它:

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

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

    2022-12-13 10:05 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有