How can I format a map over several lines with pprint?

こ雲淡風輕ζ 提交于 2019-12-05 11:10:42

问题


pprint's docs are kind of a brick wall. If you pprint a map, it comes out on one line like so: {:a "b", :b "c", :d "e"}. Instead, I'd like to be pprinted like this, optionally with commas:

{:a "b"
 :b "c"
 :d "e"}

How would one do that with pprint?


回答1:


You can set the *print-right-margin* binding:

Clojure=> (binding [*print-right-margin* 7] (pprint {:a 1 :b 2 :c 3}))
{:a 1,
 :b 2,
 :c 3}

Not exactly what you're looking for, but it might be enough?

BTW, the best way to figure this out —or at least the approach I took— is to use

Clojure=> (use 'clojure.contrib.repl-utils)
Clojure=> (source pprint)
(defn pprint 
  "Pretty print object to the optional output writer. If the writer is not provided, 
print the object to the currently bound value of *out*."
  ([object] (pprint object *out*)) 
  ([object writer]
     (with-pretty-writer writer
       (binding [*print-pretty* true]
         (write-out object))
       (if (not (= 0 (.getColumn #^PrettyWriter *out*)))
         (.write *out* (int \newline))))))
nil

Hmmrmmm.. what does with-pretty-writer do to *out*?

Clojure=> (source clojure.contrib.pprint/with-pretty-writer)
(defmacro #^{:private true} with-pretty-writer [base-writer & body]
  `(let [new-writer# (not (pretty-writer? ~base-writer))]
     (binding [*out* (if new-writer#
                      (make-pretty-writer ~base-writer *print-right-margin* *print-miser-width*)
                      ~base-writer)]
       ~@body
       (if new-writer# (.flush *out*)))))
nil

Okay, so *print-right-margin* sounds promising...

Clojure=> (source clojure.contrib.pprint/make-pretty-writer)
(defn- make-pretty-writer 
  "Wrap base-writer in a PrettyWriter with the specified right-margin and miser-width"
  [base-writer right-margin miser-width]
  (PrettyWriter. base-writer right-margin miser-width))
nil

Also, this is pretty informative:

Clojure=> (doc *print-right-margin*)
-------------------------
clojure.contrib.pprint/*print-right-margin*
nil
  Pretty printing will try to avoid anything going beyond this column.
Set it to nil to have pprint let the line be arbitrarily long. This will ignore all 
non-mandatory newlines.
nil

Anyway —and perhaps you already knew even this— if you really want to customize the way that pprint works, you can proxy clojure.contrib.pprint.PrettyWriter and pass that down by binding it to *out*. The PrettyWriter class is pretty large and intimidating, so I'm not sure if this was what you originally meant by your "brick wall" comment.




回答2:


I don't think you can do that, you'll probably need to write your own, something like:

(defn pprint-map [m]
  (print "{")
  (doall (for [[k v] m] (println k v)))
  (print "}"))


来源:https://stackoverflow.com/questions/4020186/how-can-i-format-a-map-over-several-lines-with-pprint

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!