tags:

views:

110

answers:

2

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?

+3  A: 

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 "}"))
lazy1
would have voted up if you actually used your function and show it work :)
Belun
I did -user=> (defn pprint-map [m] (print "{") (doall (for [[k v] m] (println k v))) (print "}"))#'user/pprint-mapuser=> (pprint-map {:a 1 :b 2 :c 3}){:a 1:b 2:c 3}niluser=>
lazy1
+4  A: 

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.

intuited
This method isn't going to work when you have keys/values of different lengths than :a/1.
MayDaniel
For example, see https://gist.github.com/f8eeddfcbfeff60bfa08
MayDaniel
@MayDaniel: Aye, 'tis true. That's what I meant by "not exactly". Subclassing/proxying PrettyWriter looks to be pretty daunting, but it seems to be the only way to get that behaviour and have it be integrated with `pprint`.
intuited
+1 for the lovely way of finding a solution
Belun