我是Clojure的新手,我正在尝试通过重新绑定*out*
将输出重定向到文件。在一个简单的例子中,它运作良好:
(binding [*out* (new java.io.FileWriter "test.txt")]
(println "Hi"))
这就是我所期望的,将“Hi”打印到文件test.txt。但是,如果我引入for
循环,那么事情就会出错:
(binding [*out* (new java.io.FileWriter "test.txt")]
(for [x [1 2]]
(println "Hi" x)))
这次,所有输出都转到stdout,文件为空。这是怎么回事?
我正在使用Leiningen,如果这有任何区别:
Leiningen 2.0.0 on Java 1.7.0_13 Java HotSpot(TM) 64-Bit Server VM
答案 0 :(得分:5)
你被这个懒惰的小虫咬了。
在for和绑定
中放置doall
或dorun
(binding [*out* (new java.io.FileWriter "test.txt")]
(doall (for [x [1 2]]
(println "Hi" x))))
在您的示例中,正在进行打印,然后在从绑定返回后,repl 将打印结果。因此,在打印时,绑定不再存在。
没有打印任何内容,因为结果是一个懒惰的序列,稍后将在使用时进行评估
user> (def result (binding [*out* (new java.io.FileWriter "test.txt")]
(for [x [1 2]]
(println "Hi" x))))
#'user/result
当repl打印结果时,将评估printlns:
user> result
(Hi 1
Hi 2
nil nil)
如果我们强制评估绑定中for
返回的延迟序列
没有任何内容打印到repl,
user> (def result (binding [*out* (new java.io.FileWriter "test.txt")]
(doall (for [x [1 2]]
(println "Hi" x)))))
#'user/result
user> result
(nil nil)
而输出最终在文件中:
arthur@a:~/hello$ cat test.txt
Hi 1
Hi 2