Call original method when redefining a method. (Compact float printing in IJulia)

I want to print floats (and derived types such as Unitful.Quantity{Float64, …}) compactly in IJulia / the REPL.

E.g. 0.1*3 should be echoed as 0.3 and not 0.30000000000000004.
Likewise, 0.1*3mV should be 0.3 mV and not 0.30000000000000004 mV.

The canonical way to print compactly seems to be show(IOContext(stdout, :compact=>true), 0.1*3).

To achieve this automatically for all echoes (i.e. without having to type the above show incantation in every cell), I’d like to define something like:

Base.show(io::IO, x::Float64) = 
    show(IOContext(io, :compact=>true), x)

This yields a StackOverflowError because we redefined the method in terms of itself.
The desired behaviour would be for the show in our function’s body to refer to the original float-showing method in Base.

My question is, how can we do this?
More generally: how do you call the original method when redefining a method?

(Research note: in a previous thread on the same problem this was resolved by calling Base.Grisu._show. This cannot be done anymore as “Grisu” has been replaced by “Ryu”, and Ryu only defines Base.show itself, not any inner function like _show.)

Maybe you can take a look at

https://github.com/ronisbr/PrettyNumbers.jl

To call the old method, you want invoke, or now @invoke:

julia> @which show(stdout, 3.14)
show(io::IO, x::T) where T<:Union{Float16, Float32, Float64} in Base.Ryu at ryu/Ryu.jl:111

julia> Base.show(io::IO, x::Float64) = 
             Base.@invoke show(IOContext(io, :compact=>true)::IO, x::Union{Float16, Float32, Float64})

julia> pi .^ (0,1,2)
(1.0, 3.14159, 9.8696)
1 Like

Thank you, that works nicely.
TIL about invoke.

This does not seem to work if the overriding method has the exact same signature though.

For example, I want to override show(io::IO, x::Quantity) from Unitful and use the original function definition in my new method. I currently just copy-paste the original function body (and import needed symbols), but that’s not super nice.

For that, use invoke, not @invoke.

Would you be able to explain how you did that? (Invoke old method with identical signature).

Just calling invoke in the regular way causes recursion for me.

Welcome to the discourse, I suggest starting your own post for your problem instead of trying to continue a thread that was last active over 3 years ago. A solved thread won’t be promoted as much in feeds, and the participants in this thread are far less likely to return after so long to interact with you. With very few exceptions like developers updating package announcement threads, it’s very typical to start a new thread after a month. If you like, you could link older threads in your post, but that may not be necessary because your minimum working example would usually demonstrate your issue adequately.

1 Like