【发布时间】:2025-11-20 21:20:04
【问题描述】:
我有一个使用dosync 和ref-set 创建的循环图。当我将它传递给println 时,我得到了java.lang.*Error,正如我所期望的那样,因为它实际上是在尝试打印一个无限嵌套的结构。
我发现如果我执行(str my-ref),它会创建一些看起来像vertex@23f7d873 的东西,并且实际上并没有尝试遍历结构并将所有内容打印出来,所以这解决了直接意义上的问题,但只有在以下情况下才有帮助我对打印到屏幕上的内容非常小心。我希望能够调用(println my-graph) 让它将ref 打印为某种类型的自定义文本(可能涉及str),以及其他非参考内容。
目前我有一个自定义打印函数,它自己打印结构的每个元素并完全跳过打印ref。 (事实证明,查看vertex@23f7d873 实际上并不是很有用)。这使用起来很尴尬,并且极大地阻碍了在 REPL 中对内容进行随意检查,并且还阻止了 Emacs 检查员在我处于 swank.core/break 调试事物时查看内容。
一个细节是ref 实际上是defstruct 中的一个值,它还包含一些我正在尝试正常打印的其他内容。
所以我想知道我应该走哪条路。我看到了这些选项:
- 找出
extend-type并将CharSequence协议应用于我的defstructed 结构,以便在遇到ref时它可以正常工作。这仍然需要对结构进行逐个字段检查,并在涉及ref时使用特殊情况,但至少它将问题定位到结构而不是包含该结构的任何内容。 - 找出遇到
ref时如何覆盖CharSequence协议。这允许更本地化的行为,并允许我在 REPL 上查看循环引用,即使它不在结构内。这是我的首选。 - 弄清楚如何用
toString做某事,我相信在我做println时会在某种程度上调用它。我对这个选项最无知。对其他的也很无知,但我一直在阅读Joy of Clojure,现在我都受到了启发。
同样,此解决方案应适用于 print 和 pprint 以及尝试打印循环引用时通常会出错的任何其他内容。我应该采用什么策略?
非常感谢您的任何意见。
【问题讨论】:
-
fyi,
(str my-ref)的输出几乎可以肯定是调用java.lang.Object#toString()的结果,详情如下:docs.oracle.com/javase/7/docs/api/java/lang/… -
请注意
defstruct已被defrecord取代。此外,defstruct不会创建真正的类型,因此它不能参与协议。 -
我现在意识到我实际上已经在使用
defrecord。不知道为什么我原来的帖子说defstruct。
标签: graph clojure charsequence pprint cyclic-graph