gpt4 book ai didi

graph - 如何覆盖引用类型的 println 行为

转载 作者:行者123 更新时间:2023-12-04 17:38:40 25 4
gpt4 key购买 nike

我有一个使用 dosync 创建的循环图和 ref-set .当我将此传递给 println我得到一个 java.lang.StackOverflowError正如我所料,因为它有效地试图打印一个无限嵌套的结构。

我发现如果我这样做 (str my-ref)它创建的东西看起来像 vertex@23f7d873并且实际上并没有尝试遍历结构并将所有内容打印出来,所以这从直接意义上解决了问题,但只有当我非常小心我要打印到屏幕上的内容时才有帮助。我希望能够调用(println my-graph)让它打印ref作为某种类型的自定义文本(可能涉及 str ),以及其他非引用内容。

目前我有一个自定义打印功能,它自己打印结构的每个元素并完全跳过打印 ref . (事实证明,查看 vertex@23f7d873 实际上并不是很有用)。这使用起来很尴尬,并且极大地阻碍了在 REPL 中对内容进行随意检查,并且还阻止了 Emacs 检查员在我处于 swank.core/break 时查看内容调试东西。

一个细节是ref实际上是 defstruct 中的一个值其中还包含一些我正在尝试正常打印的其他内容。

所以我想知道我应该走哪条路。我看到这些选项:

  • 弄清楚 extend-type并应用 CharSequence我的 defstruct 的协议(protocol)ed 结构,以便在遇到 ref 时它工作正常。这仍然需要对结构进行逐个字段的检查,并且在涉及 ref 时需要特殊情况。 ,但至少它将问题定位到结构而不是包含该结构的任何东西。
  • 弄清楚如何覆盖 CharSequence遇到 ref 时的协议(protocol).这允许更本地化的行为,并允许我在 REPL 上查看循环引用,即使它不在结构内。这是我的首选。
  • 弄清楚如何用 toString 做某事我相信当我做 println 时会在某种程度上被调用.我对这个选项最无知。对其他的也很无知,但我一直在阅读Joy of Clojure我现在都受到了启发。

  • 同样,此解决方案应适用于 printpprint以及在尝试打印循环引用时通常会出错的任何其他内容。我应该采用什么策略?

    非常感谢您的任何意见。

    最佳答案

    您要做的是创建一个新的命名空间并定义您自己的打印函数,这些函数模拟 clojure 打印对象的方式,并且默认为 clojure 的方法。

    详细地:

    创建一个不包括 pr-str 和 print-method 的 ns。
    创建一个多方法打印方法(完全复制 clojure.core 中的内容)
    创建一个简单地委托(delegate)给 clojure.core/print-method 的默认方法
    为 clojure.lang.Ref 创建一个不递归打印所有内容的方法

    作为奖励,如果您使用的是 clojure 1.4.0,则可以使用标记文字,以便也可以读取输出。您需要覆盖 *data-readers* map 用于自定义标记和返回 ref 对象的函数。您还需要覆盖读取字符串行为以确保为 *data-readers* 调用绑定(bind)。 .

    我为 java.io.File 提供了一个示例

     (ns my.print
    (:refer-clojure :exclude [pr-str read-string print-method]))

    (defmulti print-method (fn [x writer]
    (class x)))

    (defmethod print-method :default [o ^java.io.Writer w]
    (clojure.core/print-method o w))

    (defmethod print-method java.io.File [o ^java.io.Writer w]
    (.write w "#myprint/file \"")
    (.write w (str o))
    (.write w "\""))

    (defn pr-str [obj]
    (let [s (java.io.StringWriter.)]
    (print-method obj s)
    (str s)))

    (defonce reader-map
    (ref {'myprint/file (fn [arg]
    (java.io.File. arg))}))

    (defmacro defdata-reader [sym args & body]
    `(dosync
    (alter reader-map assoc '~sym (fn ~args ~@body))))

    (defn read-string [s]
    (binding [*data-readers* @reader-map]
    (clojure.core/read-string s)))

    现在你可以这样打电话了 (println (my.print/pr-str circular-data-structure))

    关于graph - 如何覆盖引用类型的 println 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10005102/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com