reveal icon indicating copy to clipboard operation
reveal copied to clipboard

Recursive atoms cause stackoverflow error

Open ghost opened this issue 4 years ago • 5 comments

This code will cause a stackoverflow error:

(def a (atom nil)) (def b (atom a)) (reset! a b)
a

Possible solutions are:

  1. print-method multimethod can be used to fix this for clojure repl. Maybe use that if it's available (https://clojuredocs.org/clojure.core/get-method)

  2. Don't print atoms target value in defstream IRef. It makes sense because atoms are used to opt out of the value semantics of clojure, and making recursive structures is a common use case.

ghost avatar Jan 14 '21 14:01 ghost

Hi! I'm not sure how print-method can be used to fix this, can you provide more info? Evaluating your example code in a regular REPL also tries to print it recursively (and eventually stops).

vlaaad avatar Jan 14 '21 15:01 vlaaad

You can customize how objects are formatted in repl output.

https://clojuredocs.org/clojure.core/print-method

ghost avatar Jan 14 '21 15:01 ghost

The same is true for Reveal, you can redefine the print method of you don't want to see values inside reference types. I think current default (which is the same both in Reveal and Clojure printing) makes more sense because it's useful and common to look inside atoms, even though it will fail in some cases where atoms are put inside themselves.

vlaaad avatar Jan 14 '21 18:01 vlaaad

If the goal is to be a drop in replacement for clojure repl, then implementing point 1 would be better.

ghost avatar Jan 14 '21 18:01 ghost

I think I understand what you mean: tighter integration with print-method will allow Reveal to play better with existing custom preferences for printing. I'll keep this in mind! In case you need it, here is how you can make Reveal to print only ref identities:

(require '[vlaaad.reveal.ext :as rx])

(rx/defstream IRef [*ref]
  (rx/horizontal
    (rx/raw-string (str "#reveal/" (.toLowerCase (.getSimpleName (class *ref)))) {:fill :object})
    rx/separator
    (let [hash (System/identityHashCode *ref)]
      (rx/as hash (rx/raw-string (format "0x%x" hash) {:fill :scalar})))))

vlaaad avatar Jan 14 '21 19:01 vlaaad