Clojure:将任意列表转换为字符串表示,希望懒惰?

时间:2016-11-25 08:51:32

标签: clojure

我已经厌倦了根据列表的结构编写大量代码来打印列表结构。例如,对于

'(1 2 3),我'

(apply str '(1 2 3)) 但是对于

'((1 2 3) (4 5 )),我应该

(map #(apply str %) '((1 2 3) (4 5 )))

等取决于列表的嵌套结构。

我想知道什么是优雅的函数to-string来处理任意列表结构?

下面是草图,希望学习更好的解决方案。

(defun to-string
"convert argument into string."
([x & xs] (str (to-string x) (to-string xs) "\n"))
([x] (str x))
)

提前致谢!

2 个答案:

答案 0 :(得分:3)

如果您希望获得一些一致且完全受控的格式化数据的方式,则可以使用cl-format中的clojure.pprint函数。它是常见的lisp的令人敬畏的format函数的端口。例如:例如:

user> (require '[clojure.pprint :refer [cl-format]])
nil

user> (cl-format nil "~{~a~}" '(1 2 3 4))
"1234"

user> (cl-format nil "~{~{~a~}~^ ~}" '((1 2) (3 4) (5 6)))
"12 34 56"

等等。这里有一个很好的教程:http://www.gigamonkeys.com/book/a-few-format-recipes.html以及clhs

中的更多信息 例如,你可以更进一步,并制作一些格式生成函数(或宏):

user> (defmacro make-fstring [level]
        (nth (iterate #(str "~{" % "~^ ~}") "~{~a~}") (dec level)))
#'user/make-fstring

user> (cl-format nil (make-fstring 2) '((1 2 3) (4 5 6)))
"123 456"

user> (cl-format nil (make-fstring 3) '(((1 2) (3 4) (5 6) (7 8)) 
                                        ((9 10) (11 12))))
"12 34 56 78 910 1112"

答案 1 :(得分:2)

pprint将打印格式良好的数据结构:

user=> (clojure.pprint/pprint '('(1 2 3) '(4 5 )))
('(1 2 3) '(4 5))

您可以使用with-out-str绑定*out*pprint的输出发送到字符串而不是stdout

(def s 
  (with-out-str 
     (clojure.pprint/pprint '('(1 2 3) '(4 5 )))))