如何在Clojure中将PersistentHashMap格式化输出为字符串?

34

我该如何在Clojure中将一个PersistentHashMap美观地打印成字符串?我正在寻找类似于以下的东西:

(str (pprint {... hash map here...})

我可以将其作为字符串传递


(str (pprint {:foo 1 :bar 2})) 对我来说没有问题 => {:foo 1, :bar 2} - Maurits Rijk
4个回答

47
(let [s (java.io.StringWriter.)]
  (binding [*out* s]
    (clojure.pprint/pprint {:a 10 :b 20}))
  (.toString s))

编辑:简洁版本如下:

(with-out-str (clojure.pprint/pprint {:a 10 :b 20}))

6
你也可以使用 with-out-str 函数,它会剔除所有的绑定内容。 - Rayne
如果其他线程输出到 out,这个代码还能正常工作吗?它是线程安全的吗? - yazzapps.com
1
@Zubair - 绑定宏始终是线程安全的。新的 var 绑定是基于每个线程创建的,而根绑定保持不变。请参阅 http://clojure.org/vars - Alex Stoddard
1
@Rayne 感谢提醒。第一次查找时我在clojuredocs上找不到with-out-str,但现在已经找到了。因此,更新后的解决方案是:(with-out-str (clojure.pprint/pprint {:a 10 :b 20})) - Shantanu Kumar
1
请将此最后一条评论发布为答案 - 它很容易被忽略 ;) - bluegray
方便的宏:(defmacro pprint-str [forms] `(with-out-str (clojure.pprint/pprint (do ~forms)))) - Paul Legato

20

这应该有所帮助:

(clojure.pprint/write {:a 1 :b 2} :stream nil)

根据 clojure.pprint/write 函数 文档 ,如果 :stream 参数为 nil,则返回字符串结果,否则返回 nil。


在ClojureScript中运行。非常好的答案。 - Chris Murphy

16
user=> (import java.io.StringWriter)
java.io.StringWriter
user=> (use '[clojure.pprint :only (pprint)])
nil
user=> (defn hashmap-to-string [m] 
  (let [w (StringWriter.)] (pprint m w)(.toString w)))
#'user/hashmap-to-string
user=> (hashmap-to-string {:a 1 :b 2})
"{:a 1, :b 2}\n"

编译器抱怨“CompilerException java.lang.RuntimeException: Unable to resolve symbol: w in this context”。原始帖子可以工作,但Rayne的编辑似乎破坏了它! - AnnanFay

9
(pr-str {:a 1 :b 2}) ;; => "{:a 1, :b 2}"

我尝试过这个,但只能在REPL中运行。为了让它在程序中运行,我应该导入什么? - yazzapps.com
1
pr-str是clojure.core命名空间的一部分。您不需要导入任何特殊的内容。 - mtyaka
2
是的,你说得对,我之前做错了。现在它可以工作了,除了 (pr-str {:a 1 :b {:a 2 :b 2}}) 返回的是 {:a 1, :b {:a 2, :b 2}}。有没有办法让它返回带有换行符的结果呢? - yazzapps.com
pr-str 不适用于“漂亮打印”(例如带有换行符)。 - David J.
prn-str 在返回的字符串中包含换行符。 - Jeff Terrell Ph.D.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接