Как переопределить поведение println для ссылочных типов

У меня есть циклический граф, который я создал с помощью dosyncи набор ссылок. Когда я передаю это в println, я получаю java.lang.StackOverflowError, как и ожидал, потому что он эффективно пытается напечатать бесконечно вложенную структуру.

Я обнаружил, что если я делаю (str my-ref), создается что-то похожее на vertex@23f7d873и на самом деле не пытается пройти через структуру и распечатать все , так что это решает проблему в прямом смысле, но помогает только тогда, когда я очень внимательно отношусь к тому, что я печатаю на экране. Я хотел бы иметь возможность вызывать (println my-graph), чтобы он печатал refкак некоторый тип пользовательского текста (возможно, с участием str), и другие вещи, не связанные с рефери, обычно.

В настоящее время у меня есть пользовательская функция печати, которая печатает каждый элемент структуры отдельно и полностью пропускает печать ref. (Оказывается, смотреть на vertex@23f7d873на самом деле не очень полезно). Это неудобно в использовании и сильно мешает выполнять случайную проверку материала в REPL, а также не позволяет инспектору Emacs просматривать материал, пока я нахожусь в swank.core/breakотладочной штуке.

Одна деталь заключается в том, что refна самом деле является значением в defstruct, которое также содержит некоторые другие данные, которые я пытаюсь напечатать в обычном режиме.

Вот я и думаю, по какому пути мне идти. Я вижу следующие варианты:

  1. Определите extend-typeи примените протокол CharSequenceк моей структуре defstructed, чтобы при встрече с refработает правильно. Это по-прежнему требует полевой проверки структуры и особого случая, когда речь идет о ref, но, по крайней мере, это локализует проблему в структуре, а не во всем, что содержит структуру.
  2. Выясните, как переопределить протокол CharSequence, когда он встречает ref. Это обеспечивает еще более локализованное поведение и позволяет мне просматривать циклическую ссылку в REPL, даже если она не находится внутри структуры. Это мой предпочтительный вариант.
  3. Выясните, как что-то сделать с toString, который, как мне кажется, вызывается на каком-то уровне, когда я делаю println. Я самый невежественный об этом варианте.О других я тоже ничего не знаю, но я читал Joy of Clojure, и теперь я полностью вдохновлен.

Подобным образом это решение должно применяться к printи pprintи ко всему остальному, что обычно выдает ошибку при попытке напечатать циклическую ссылку. Какую стратегию мне следует использовать?

Большое спасибо за любой вклад.

5
задан Sonicsmooth 4 April 2012 в 04:49
поделиться