Как я могу отформатировать карту в несколько строк с помощью pprint?

Документы pprint похожи на кирпичную стену. Если вы распечатаете карту, она будет представлена ​​одной строкой: {:a "b", :b "c", :d "e"}. Вместо этого я бы хотел, чтобы меня печатали так, необязательно с запятыми:

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

Как бы это сделать с pprint?


person Rayne    schedule 26.10.2010    source источник


Ответы (2)


Вы можете установить привязку *print-right-margin*:

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

Не совсем то, что вы ищете, но может быть достаточно?

Кстати, лучший способ понять это — или, по крайней мере, подход, который я выбрал — это использовать

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

Хммммм... что with-pretty-writer делает с *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

Итак, *print-right-margin* звучит многообещающе...

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

Кроме того, это довольно информативно:

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

В любом случае — и, возможно, вы уже знали даже об этом — если вы действительно хотите настроить способ работы pprint, вы можете proxy clojure.contrib.pprint.PrettyWriter и передать его, привязав его к *out*. Класс PrettyWriter довольно большой и пугающий, поэтому я не уверен, что это то, что вы изначально имели в виду под своим комментарием «кирпичная стена».

person intuited    schedule 26.10.2010
comment
Этот метод не будет работать, если у вас есть ключи/значения другой длины, чем :a/1. - person MayDaniel; 26.10.2010
comment
@MayDaniel: Да, это правда. Вот что я имел в виду под не совсем так. Создание подклассов/проксирования PrettyWriter выглядит довольно устрашающе, но это единственный способ получить такое поведение и интегрировать его с pprint. - person intuited; 27.10.2010
comment
Также есть соответствующие документы по адресу code.google.com/p/clojure-contrib. /wiki/PrettyPrinting . - person Paul Legato; 06.05.2013

Я не думаю, что вы можете это сделать, вам, вероятно, нужно будет написать что-то вроде:

(defn pprint-map [m]
  (print "{")
  (doall (for [[k v] m] (println k v)))
  (print "}"))
person lazy1    schedule 26.10.2010
comment
проголосовал бы, если бы вы действительно использовали свою функцию и показали, что она работает :) - person Belun; 27.10.2010
comment
Я сделал - user=› (defn pprint-map [m] (print {) (doall (for [[kv] m] (println kv))) (print })) #'user/pprint-map user=› ( pprint-map {:a 1 :b 2 :c 3}) {:a 1 :b 2 :c 3 }nil user=› - person lazy1; 28.10.2010