漂亮的印刷使用Clojure中的一个自定义的方法记录(pretty-printing a recor

2019-07-20 21:12发布

在Clojure的1.5.0,我怎么能为我自己的记录类型,与defrecord定义的自定义美化打印机。

(defrecord MyRecord [a b])

(defmethod print-method MyRecord [x ^java.io.Writer writer]
  (print-method (:a x) writer))

(defmethod print-dup MyRecord [x ^java.io.Writer writer]
  (print-dup (:a x) writer))

(println (MyRecord. 'a 'b)) ;; a -- OK
(clojure.pprint/pprint (MyRecord. 'a 'b)) ;; {:a a, :b b} -- not OK, I want a

我想clojure.pprint/pprint也使用我的打印机cutsom(现在,应该只是漂亮的版画无论是在现场a用于说明目的的记录)。

Answer 1:

clojure.pprint命名空间使用不同的调度机制,则clojure.core打印功能。 您需要使用with-pprint-dispatch定制pprint。

(clojure.pprint/with-pprint-dispatch print  ;;Make the dispatch to your print function
  (clojure.pprint/pprint (MyRecord. 'a 'b)))

要自定义简单的调度程序,添加类似:

(. clojure.pprint/simple-dispatch addMethod MyRecord pprint-myrecord)


Answer 2:

这已经非常混乱,有正确答案各地不同地方蔓延问题的不同部分,所以我把它放在一起的希望,有人可能会节省一些时间。

我通过定义多方法的所有排列去print-methodprint-dup ,和simple-dispatch的defrecord,并设置动态VAR *print-pprint-dispatch**print-dup* 。 我把一个例子defrecord通过两个prpprint ,并与下面的流程图上来。 这是有道理的,现在我可以一次看到的一切。

置换代码是蛮力; 我只是看着输出和直接创建Visio图表。 没有什么花哨。

(ns print-test
  (:require [clojure.pprint :as pp]))


(defrecord tr000 [val])
(defrecord tr001 [val])
(defrecord tr010 [val])
(defrecord tr011 [val])
(defrecord tr100 [val])
(defrecord tr101 [val])
(defrecord tr110 [val])
(defrecord tr111 [val])


;;(defmethod print-method       tr000 [obj writer]  (.write writer "tr000 print-method"))
;;(defmethod print-dup          tr000 [obj writer]  (.write writer "tr000 print-dup"))
;;(defmethod pp/simple-dispatch tr000 [obj]         (.write *out* "tr000 simple-dispatch"))

;;(defmethod print-method       tr001 [obj writer]  (.write writer "tr001 print-method"))
;;(defmethod print-dup          tr001 [obj writer]  (.write writer "tr001 print-dup"))
(defmethod pp/simple-dispatch tr001 [obj]         (.write *out* "tr001 simple-dispatch"))

;;(defmethod print-method       tr010 [obj writer]  (.write writer "tr010 print-method"))
(defmethod print-dup          tr010 [obj writer]  (.write writer "tr010 print-dup"))
;;(defmethod pp/simple-dispatch tr010 [obj]         (.write *out* "tr010 simple-dispatch"))

;;(defmethod print-method       tr011 [obj writer]  (.write writer "tr011 print-method"))
(defmethod print-dup          tr011 [obj writer]  (.write writer "tr011 print-dup"))
(defmethod pp/simple-dispatch tr011 [obj]         (.write *out* "tr011 simple-dispatch"))

(defmethod print-method       tr100 [obj writer]  (.write writer "tr100 print-method"))
;;(defmethod print-dup          tr100 [obj writer]  (.write writer "tr100 print-dup"))
;;(defmethod pp/simple-dispatch tr100 [obj]         (.write *out* "tr100 simple-dispatch"))

(defmethod print-method       tr101 [obj writer]  (.write writer "tr101 print-method"))
;;(defmethod print-dup          tr101 [obj writer]  (.write writer "tr101 print-dup"))
(defmethod pp/simple-dispatch tr101 [obj]         (.write *out* "tr101 simple-dispatch"))

(defmethod print-method       tr110 [obj writer]  (.write writer "tr110 print-method"))
(defmethod print-dup          tr110 [obj writer]  (.write writer "tr110 print-dup"))
;;(defmethod pp/simple-dispatch tr110 [obj]         (.write *out* "tr110 simple-dispatch"))

(defmethod print-method       tr111 [obj writer]  (.write writer "tr111 print-method"))
(defmethod print-dup          tr111 [obj writer]  (.write writer "tr111 print-dup"))
(defmethod pp/simple-dispatch tr111 [obj]         (.write *out* "tr111 simple-dispatch"))


(def t000 (->tr000 10))
(def t001 (->tr001 20))
(def t010 (->tr010 30))
(def t011 (->tr011 40))
(def t100 (->tr100 50))
(def t101 (->tr101 60))
(def t110 (->tr110 70))
(def t111 (->tr111 80))
(def recs [t000 t001 t010 t011 t100 t101 t110 t111])


(def dt (java.time.LocalTime/now))
(defmethod print-dup java.time.LocalTime [obj writer] (.write writer "datetime_dup"))

(println "(pr ...) outputs the following")
(doseq [rec recs]
  (doseq [prppd [nil #(.write *out* "pprint-dispatch with" %)]]
    (binding [pp/*print-pprint-dispatch*
              (if prppd #(.write *out* (str "pprint-dipatch-with" %))
                  pp/*print-pprint-dispatch*)]
      (doseq [pd [false true]]
        (binding [*print-dup* pd]
          (let [ppdstr (format "%6s" (boolean pp/*print-pprint-dispatch*))
                dupstr (format "%6s" *print-dup*)
                outstr (pr-str rec)]
            (binding [*print-dup* false]
              (println ppdstr dupstr ":" outstr))))))))

(println "\n(pprint ...) outputs the following")
(doseq [rec recs]
  (doseq [prppd [false true]]
    (binding [pp/*print-pprint-dispatch*
              (if prppd #(.write *out* (str "pprint-dipatch-with" %))
                  pp/*print-pprint-dispatch*)]
      (doseq [pd [false true]]
        (binding [*print-dup* pd]
          (let [outstr
                (with-out-str
                  (pp/pprint {:ppdstr prppd
                              :dupstr pd
                              :dt dt
                              :strobj rec}))]
            (binding [*print-dup* false]
              (println outstr "\n"))))))))


Answer 3:

也许并不理想,但我还没有找到优于prpr-str

例如REPL会话:

  (ns my-ns)

  (defprotocol Foo
    (bazfn [this]))

  (defrecord Bar [a]
    Foo
    (bazfn [this] 123))


  (pr-str (Bar. "ok")) ;;=> "#my_ns.Bar{:a \"ok\"}"
  (pr (Bar. "ok"))     ;; prints the same as above


文章来源: pretty-printing a record using a custom method in Clojure