【问题标题】:Customizing the printing of maps by :type in Clojure在 Clojure 中通过 :type 自定义地图的打印
【发布时间】:2017-03-21 16:47:14
【问题描述】:

把这张地图打印出来很丑:

  {:type :move,
   :name :boost,
   :from
   {:nodeid :plus,
    :name :left-operand,
    :value
    {:args [:result :right-operand],
     :f
     #object[fargish.workspace_test$fn__159675$fn__159678 0xb3f518f "fargish.workspace_test$fn__159675$fn__159678@b3f518f"]},
    :dockclass :input,
    :ref [:plus :left-operand]},
   :to
   {:nodeid :source11,
    :name :output,
    :value 11,
    :dockclass :output,
    :ref [:source11 :output]},
   :do
   #object[fargish.workspace$do_boost 0x179d226e "fargish.workspace$do_boost@179d226e"],
   :do-hypothetically
   #object[fargish.workspace$do_hypothetical_boost 0x68d6475a "fargish.workspace$do_hypothetical_boost@68d6475a"]}

大多数时候,我不需要看到大部分内容。我希望它看起来大致像这样:

#boost{:from [:plus :left-operand] :to [:source11 :output]}

Clojure 是否提供了一个钩子让我插入代码,以便如果映射的:type 键的值为:movestr 将调用我编写的函数来生成字符串?

我已经调查过print-method。如果我理解正确,那将扩展一个多方法,该方法在参数类型上调度,即。 clojure.lang.PersistentArrayMap,而不是地图的:type。 AFAIK,没有办法“转发”到先前定义的多方法,否则我可以为 clojure.lang.PersistentArrayMap 写一个print-method,它查看:type,然后调用泛型方法,如果它的值不是@987654333 @。

即使只是自定义 pprint 也会有所帮助。从理论上讲,pprint 是非常可定制的,但我还没有找到 documentation 来解释如何。 This 不完整,表明 pprint 还没有真正完成。

影响pprint 的输出会很好,但这并不是绝对必要的。只要能够影响strprint 就会有很大帮助。

【问题讨论】:

    标签: clojure string-formatting pretty-print


    【解决方案1】:

    print-method already looks at :type 对象元数据上的键。只需将:type 安排在元数据中,而不是(或附加于)实际地图本身,您就可以定义自己的打印方法。

    【讨论】:

    • 恐怕您只能靠自己使用 pprint。它的使用几乎没有核心打印设施那么多,而且我认为因此它没有那么灵活:很少有人关心扩展它。我认为你能做的最好的事情是:定义一种新的 pprint 调度方法来代替 simple-dispatch,在 your-dispatch 上实现你想要的任何自定义内容,然后将其他决策委托给 simple-dispatch。但这并不像使用 print-method 那样简单,因为它默认不考虑元数据。
    • 你应该写下这个答案。 OP 明确询问了 pprint。
    • 哇,它有效!轻松,甚至! (@LeonGrapenthin 问了我下一个问题。)谢谢。
    • @LeonGrapenthin 我会澄清这个问题。我很高兴能够修改 print 的行为。 pprint 也不错,但不是绝对必要的。
    • @BenKovitz 如果您发现我关于扩展 pprint 的建议很有帮助,并且它们解决了您的问题,您应该添加自己的答案,解释如何扩展 pprint 的详细信息。我所说的内容非常随意,对将来可能阅读此问题的其他任何人都没有太大用处。 (或者如果您的意思是我的扩展 print-method 的建议很容易并且足够,而您根本没有扩展 pprint,那么请不要介意并接受我的回答。
    【解决方案2】:

    有一个名为zprint 的漂亮打印包,您可以使用它让您非常接近您想要的内容,并且当您的输出很大且难以从视觉上理解时,您仍然可以享受漂亮打印的好处。我在下面给出了一些例子:

    ; Basic zprint pretty-print of a similar map.  Note that it orders the keys
    ; alphabetically
    
    user=> (zprint soq)
    {:do #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
     :do-hypothetically #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
     :from {:dockclass :input,
            :name :left-operand,
            :nodeid :plus,
            :ref [:plus :left-operand],
            :value {:args [:result :right-operand],
                    :f #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>}},
     :name :boost,
     :to {:dockclass :output,
          :name :output,
          :nodeid :source11,
          :ref [:source11 :output],
          :value 11},
     :type :move}
    
    ; You can order the keys so the ones you care about come in the order
    ; you want.
    
    user=> (zprint soq {:map {:key-order [:name :from :to]}})
    {:name :boost,
     :from {:name :left-operand,
            :dockclass :input,
            :nodeid :plus,
            :ref [:plus :left-operand],
            :value {:args [:result :right-operand],
                    :f #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>}},
     :to {:name :output,
          :dockclass :output,
          :nodeid :source11,
          :ref [:source11 :output],
          :value 11},
     :do #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
     :do-hypothetically #<Fn@4d0e1990 clojure.lang.PersistentList/Primordial>,
     :type :move}
    
    ; You can get zprint to ignore keys completely
    
    user=> (zprint soq {:map {:key-order [:name :from :to] :key-ignore-silent [[:from :name] :dockclass :nodeid :value :do :do-hypothetically :type [:to :name]]}})
    {:name :boost,
     :from {:ref [:plus :left-operand]},
     :to {:ref [:source11 :output]}}
    
    ; You can configure zprint to do this all the time
    
    user=> (zprint.core/set-options! {:map {:key-order [:name :from :to] :key-ignore-silent [[:from :name] :dockclass :nodeid :value :do :do-hypothetically :type [:to :name]]}})
    
    ; Now you just zprint it...
    
    user=> (zprint soq)
    {:name :boost,
     :from {:ref [:plus :left-operand]},
     :to {:ref [:source11 :output]}}
    

    您可以使用 ~/.zprintrc 文件配置 zprint 以始终​​执行此操作。

    您还可以使用 czprint 对其进行着色,并且您也可以使用 :key-color 映射以任何您想要的方式为键着色。当我查看整个地图序列时,我发现这很有用 - 更改一个键的颜色并以我想要的方式对这些键进行排序可以让我更轻松地理解一系列地图。

    构建一个函数来查看 :type 然后调用 zprint 会很简单 任何适合该类型的选项。当然, :ref 仍然存在,但是当您有大量输出时,需要权衡取舍,并且 zprint 漂亮的打印会开始,它更容易阅读和理解。

    【讨论】:

      猜你喜欢
      • 2015-10-05
      • 1970-01-01
      • 2021-07-10
      • 1970-01-01
      • 2013-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      相关资源
      最近更新 更多