当我在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)
答案 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中被调用时,它会保存输出,直到它完成它自己的为止,因此异常将意味着收集的其他位(打印内打印)调用不会被刷新。