第二个println语句会发生什么?(Clojure回复)
当我在clojure REPL中调用这个小函数时,它只打印第一个hello world,而不是hello mars。为什么呢?它不是懒惰的(据我所知),否则异常不会被命中,另外,它告诉我println会导致刷新第二个println语句会发生什么?(Clojure回复),clojure,Clojure,当我在clojure REPL中调用这个小函数时,它只打印第一个hello world,而不是hello mars。为什么呢?它不是懒惰的(据我所知),否则异常不会被命中,另外,它告诉我println会导致刷新 (defn foo
(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])
)
输出:
(无)无你好,世界
与许多行星交谈测试异常。repl/foo/fn--6580
(表格-init13300486174634970.clj:5)
好的,我有个主意。Map返回一个惰性seq。repl在试图实现它的映射上调用println(或类似),调用.toString()(或类似)。在内部,当在print/ln中调用print/ln时,它会保存输出,直到它自己完成为止,因此异常将意味着收集的其他位(print内的print)调用不会刷新 首先,
map
实际上是惰性的,因此foo
返回一个LazySeq
,当REPL打印它时,它会被强制执行。现在,当我使用bare Clojure(java-jar Clojure.jar
)运行您的示例时,我得到以下输出:
user=> (foo nil)
nil Hello, World!
(Hello, Mars
Exception talking to many planets user/foo/fn--1 (NO_SOURCE_FILE:5)
user=>
我在Clojure 1.4.0和1.5.1中得到了相同的结果
现在,如果我通过leinrepl
运行,就会得到您描述的输出。因此,nrepl链中的某些内容似乎正在影响打印方式。这是有意义的,因为nrepl设计用于通过网络与客户端通信。然而,在处理这个案例的过程中,似乎有一个小错误。或者在打印值时,它会将换行符上的flush重新绑定为false?对不起,我还没有深入到代码中给出更明确的答案
顺便说一句,如果将函数调用包装在
println
中,即(println(foo nil))
,则会得到上面所示的预期输出。我刚刚尝试了相同的代码,我看到了你好,Mars在抛出异常
之前打印code>,如果您没有看到这种奇怪的行为,我会预测到这一点<代码>零你好,世界!(你好,Mars Exception talking to many planets user/foo/fn--6(NO_SOURCE_FILE:19)
。Clojure版本是1.5.1。你在使用哪个jvm?对我来说:java版本“1.7.0_25”OpenJDK运行时环境(IcedTea 2.3.12)(7u25-2.3.12-4ubuntu3)OpenJDK 64位服务器虚拟机(构建23.7-b01,混合模式)我已经在lubuntu上试用了版本“1.7.0_25”OpenJDK运行时环境(IcedTea 2.3.10)(7u25-2.3.20-lubuntu0.13.04.2)OpendJDK Zero虚拟机(构建22.0-b10,混合模式)
和Windows 7中的java版本“1.7.0_21”java(TM)SE运行时环境(构建1.7.0_21-b11)热点java(TM)客户机虚拟机(构建23.21-b01,混合模式)
,我在这两个方面都得到了相同的结果。Juan,非常有趣。谢谢。我将在其他几个虚拟机上试用。我在java-cp Clojure.jar Clojure.main中使用了裸Clojure REPL,但是当我在REPL-y客户端中试用它时,leiningen使用它连接到nREPL服务器,我看到了与您相同的情况。使用哪个在调用println
后,我不认为抛出的异常会妨碍缓冲区的刷新。但我不知道为什么您会看到这种行为:(好的,知道了(我想),它看起来像是REPL-y首先在它自己的缓冲区中捕获整个表达式的结果,因此当出现异常时,它只打印该结果,而不是为stdout缓冲的结果。可以通过这一点观察到(map(fn[x](Thread/sleep 5000)(println“x”)x)[1 2 3]),即使println调用flush REPL-y,直到15秒后才打印任何内容。