我有这段代码:
(def x 10)
(def io (java.io.StringWriter.))
(with-redefs [x 11]
(with-redefs [io (java.io.StringWriter.)]
(.write io "one"))
(with-redefs [io (java.io.StringWriter.)]
(.write io "two")
(.toString io)))
(with-redefs [x 11]
(with-redefs [*out* (java.io.StringWriter.)]
(print "one"))
(with-redefs [*out* (java.io.StringWriter.)]
(print "two")
(.toString *out*)))
第一个with-redefs块返回"两个"正如所料。第二个返回" onetwo"。就好像它出于某种原因重新使用同样的模拟**一样。这是预期的行为吗?
答案 0 :(得分:2)
问题在于,您关心的*out*
是线程本地的,而不是根值。尝试:
(with-redefs [x 11]
(binding [*out* (java.io.StringWriter.)]
(print "one"))
(binding [*out* (java.io.StringWriter.)]
(print "two")
(.toString *out*)))
with-redefs
宏仅改变根绑定;任何线程本地绑定都不受影响。当代码由REPL服务器执行时,它是在将*out*
重新绑定到客户端特定的编写器的上下文中完成的,这样就可以捕获输出并将其发送回客户端以供显示(否则它会转到服务器的标准输出。如果从命令行而不是REPL运行,原始代码可能会起作用。