Open dgtized opened 2 years ago
I think there are three separate issues wrapped up in here.
1) control over floating point printing. 2) extensible formatting of tagged-literals, similar to what is supported symbols.
.toFixed is converting the output element type to string too early, so the visitor pass detects it as a string
There are two ugly workarounds for your immediate needs:
1) Do something like (symbol (.toFixed x 2))
, abusing the fact that Clojure's symbol constructor follows the garbage-in, garbage-out philosophy.
2) Monkey-patch the print-method for Float and Double:
(defmethod print-method Float [o, ^Writer w]
(cond
(= Float/POSITIVE_INFINITY o) (.write w "##Inf")
(= Float/NEGATIVE_INFINITY o) (.write w "##-Inf")
(.isNaN ^Float o) (.write w "##NaN")
:else (.write w (.toFixed o 2))))
is there a way to control formatting by passing through a fixed float
We delegate to Clojure here and - unfortunately - Clojure's print-method for numbers (modified above) does not provide a parameter for controlling this.
I'd be open to providing an option for this, but I'm hesitant because duplicating an underlying print method for a primitive decouples us from future changes. For instance, when #inf
was added, Fipp got support for it for free by delegating to Clojure.
Is there a way to pass through formatting instructions during the EDN conversion prior to visiting each element
No. An intentional design feature of the EDN conversion is that it is formatting-agnostic. In theory, a custom type could be used to pass through formatting hints, but I haven't seen a good reason to do so yet.
Would it make sense to add another map key like :symbols, such as :tagged-literals that supported overriding the printer visitor for each tagged literal?
Maybe? I'd have to think about the implications of that. My gut reaction is to say no unless additional use cases are understood.
Should I look into writing my own EdnPrinter with this functionality?
That's the less hacky workaround: Simply copy/paste this part of the implementation and modify as necessary. It's small enough to be a low maintenance burden.
--
In summary, let me know if one of the workarounds works for you. If number formatting control is important, we can survey/lobby other printers and Clojure itself in case it makes sense to add a clojure.core/number-precision or similar.
Oh, the symbol
approach is a really useful hack to be aware of for pass-through even if it's extra gross. I think that might be enough of a work-around for the cases I'm dealing with for now. Otherwise I'll take a look at my own EdnPrinter
implementation with the :tagged-literals
override. That seems like the correct spot to override output formatting, but I can understand if it's too niche a use case to update here.
Thanks for pointing out the print-method override approach, but I think I want scoped control over the precision of output and not a global change. It's a useful override if the floating point values are coordinates in a vector, but less useful if they represent something else. That said, I guess it's also possible to override the display of all floating point numbers using a custom EdnVisitor
by overriding visit-number
to check integer?
, float?
and format the output there.
Thanks for all the help, I'm trying to think how this could be better documented, but this discussion might be sufficient for now. I'll play around with the symbol and custom EdnVisitor
with tagged-literal overrides as those seem to make the most sense and then see if anything to document jumps out.
I've been working with debugging larger datastructures containing many instances of the shape and vector objects from https://github.com/thi-ng/geom. I've found fipp to be very useful for ensuring the debug output is readable, so thank you.
However, I've also found it useful to simplify the output by doing tricks like:
So that instead of verbose output like
It's simplified to
However,
.toFixed
is converting the output element type to string too early, so the visitor pass detects it as a string and instead it prints like:I've succeeded in getting output without the string by rounding each of the x,y coordinate values to two decimal places, keeping them a number, but that occasionally expands back to the max width for each coordinate due to floating point representation errors.
So my question is, is there a way to control formatting by passing through a fixed float, or is this simply behavior that is out of the scope of this library?
Is there a way to pass through formatting instructions during the EDN conversion prior to visiting each element? Or is this attempting to do the transformation in the wrong place, and instead should look into something akin to fipp.clojure to adjust formatting in the output. However based on https://github.com/brandonbloom/fipp/blob/a4cb207f2fec08219a1bba115a69819b2c7a256c/src/fipp/edn.cljc#L55-L58 It looks like the pretty symbols override only works for
'(symbol a b c)
forms, but there does not appear to be equivalent functionality for overriding tagged-literals in https://github.com/brandonbloom/fipp/blob/a4cb207f2fec08219a1bba115a69819b2c7a256c/src/fipp/edn.cljc#L71-L76 Would it make sense to add another map key like:symbols
, such as:tagged-literals
that supported overriding the printer visitor for each tagged literal? Should I look into writing my ownEdnPrinter
with this functionality?Happy to work on a PR if there is a recommended approach or even just to document this behavior, but am uncertain which way is intended. Thanks again for creating such a useful pretty printer interface.