【问题标题】:pretty-printing a record using a custom method in Clojure在 Clojure 中使用自定义方法漂亮地打印记录
【发布时间】:2013-03-02 21:14:41
【问题描述】:

在 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 中的任何内容)。

【问题讨论】:

    标签: clojure pretty-print multimethod pprint


    【解决方案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)
    

    【讨论】:

    • 把它留在这里,因为这就是我到达这里的原因:pprint-myrecord 函数应该写入*out*,而不是返回字符串。
    【解决方案2】:

    这非常令人困惑,问题的不同部分的正确答案分布在不同的地方,所以我把它们放在一起,希望有人可以节省一些时间。

    我经历了为 defrecord 定义多方法 print-methodprint-dupsimple-dispatch 以及设置动态变量 *print-pprint-dispatch**print-dup* 的所有排列。我通过prpprint 放了一个示例defrecord,并提出了以下流程图。现在我可以立即看到所有内容,这很有意义。

    置换码是蛮力的;我只是查看了输出并直接创建了 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"))))))))
    

    【讨论】:

      【解决方案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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-08
        • 2021-01-08
        • 2020-07-30
        • 2021-07-28
        • 1970-01-01
        • 2015-07-03
        相关资源
        最近更新 更多