kkinnear/zprint

Allow finer configuration of how certain Objects get printed

MrEbbinghaus opened this issue · 3 comments

I just came across the issue that ArrayLists do not break.

(def alist (java.util.ArrayList.))

(dotimes [_ 100] (.add alist "SOME STRING"))

(zprint/czprint alist 30)
["SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING"]

The problem is, that this looks like a clojure/edn value that should be broken, but it is just a string from .toString.

(.toString alist)
"[SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING, SOME STRING]"

Coercing that ArrayList to a clojure vector would solve that problem.

(vec alist)
["SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING" ...]
 
(zprint/czprint (vec alist) {:width 30, :max-length 8})
["SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING"
 ...]

Is there a way to configure that behaviour?
I imagine something like:

(def config {:width 30, 
             :max-length 8, 
             java.util.List {:transform vec}}
(zprint/czprint alist config)
["SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING"
 "SOME STRING" "SOME STRING"
 ...]

This could work in general:

(zprint/czprint 5 
  {java.lang.Number {:transform #(str "Integer(" % ")")}})

; Integer(5)

(Notation is just an example, of course.)

Thanks for asking! This is an interesting problem, as the java.util.ArrayList doesn't trigger any of the "it must be one of these, print it this way", and just falls through into printing as a string. I'm sure that there are other Java types that will end up the same way. I'm tentatively open to the idea of some sort of class or type based transformation, although I'm not clear on where to put it. One option is for the things that don't show up as something else, another is to do it prior to the tests for what something is -- which is what you are implying, I think.

I'll give this some thought and see what I can figure out. If you happen to have any other examples of real-world Java classes that are getting the same (.toString ...) treatment, it would be interesting to have more than one example to experiment with and to write tests for. Thanks!

Maybe this is a case for clojure.datafy?

something -datafy-> data -zprint-> formatted string feels like a good way to separate the concerns.

This is now implemented in 1.2.9.

There is a new option map key to transform random Java classes into other, more manageable data types: :modify-sexpr-by-type.

I wrote up a whole big thing in the reference manual about how this works (using your example data above). Search the reference manual for :modify-sexpr-by-type and hopefully that will explain how to do what you want. Let me know if it isn't clear.