第二次println声明会发生什么? (Clojure repl)

时间:2013-12-07 04:53:46

标签: clojure

当我在clojure REPL中调用这个小函数时,它只打印第一个hello世界,而不是hello mars。这是为什么?它不是懒惰的(据我所知)否则异常不会被击中,另外SO告诉我println会导致刷新。

(defn foo                                                                                                                                                           
     "I don't do a whole lot."                                                                                                                                         
     [x]                                                                                                                                                               
     (println x "Hello, World!")                                                                                                                                       
     (map (fn [x] (let [_ (println "Hello, Mars")                                                                                                                      
                        __ (throw (Exception. "talking to many planets"))]                                                                                             
                    { :aliens? false }                                                                                                                                 
                   )) [1 2 3])                                                                                                                                        
)    

输出:

  

(foo nil)无论你好,世界!

     

与许多行星交谈的例外test.repl / foo / fn - 6580   (形状init13300486174634970.clj:5)

2 个答案:

答案 0 :(得分:4)

首先,map实际上是懒惰的,因此foo返回LazySeq,然后在REPL打印时强制它java -jar clojure.jar。现在,当我使用裸Clojure(user=> (foo nil) nil Hello, World! (Hello, Mars Exception talking to many planets user/foo/fn--1 (NO_SOURCE_FILE:5) user=> )运行您的示例时,我得到以下输出:

lein repl

我在Clojure 1.4.0和1.5.1中得到了相同的结果。

现在如果我通过println运行,我会得到您描述的输出。因此,似乎nrepl链中的某些东西正在影响事物的打印方式。这是有道理的,因为nrepl旨在通过网络与客户端进行通信。然而,在处理此案件时似乎存在轻微的错误。或者,在打印值时,它可能会将 flush-on-newline 重新绑定为false?对不起,我没有深入研究代码,给出更明确的答案。

顺便提一下,如果您将函数调用包装在(println (foo nil))中,即{{1}},那么您将获得上面显示的预期输出。

答案 1 :(得分:1)

好的,我有个主意。 Map返回一个懒惰的seq。 repl在地图上调用println(或类似的),试图实现它,调用.toString()(或类似的)。在内部,当print / ln在print / ln中被调用时,它会保存输出,直到它完成它自己的为止,因此异常将意味着收集的其他位(打印内打印)调用不会被刷新。