How to stop `show` from printing a type's fully qualified name?

Say I have a type, X, and I overload its show(). When the type name comes up in other contexts, such as in an array, it still prints the fully qualified name:

julia> module M
           struct X
               x
           end
           
           Base.show(io::IO, x::X) = print(io, "X($(x.x))")
           
           println([X(1),X(2)])
       end
Main.M.X[X(1), X(2)]
Main.M

Is it bad form to overload show(::IO, Type{X}) to stop doing that? Is there a way to do that only in certain contexts (such as, if it’s nested inside another object in the same module)?

julia> module M
           struct X
               x
           end
           
           # NOTE: Here I ONLY overload the Type printing, because the rest of the default behavior works great.
           Base.show(io::IO, x::Type{X}) = print(io, "X")
           
           println([X(1),X(2)])
       end
X[X(1), X(2)]
Main.M

Asked on StackOverflow as well:

When making a custom type, like a struct , the author of the custom type often provides a version of Base.show specialized to that type. Here is a good pattern to follow:

struct MyString
    s::String
end

mystring = MyString("my string") # shows: MyString("my string")

# this is used to handle a call to `print`
Base.show(io::IO, x::MyString) = print(io, x.s)
# this is used to show values in the REPL and when using IJulia
Base.show(io::IO, m::MIME"text/plain", x::MyString) = print(io, x.s)

mystring = MyString("my string") # shows: my string
print(mystring)                  # shows: "my string" 
mystring = MyString("my string") # shows: MyString("my string")

this information comes from a Discourse entry written by Steven G. Johnson

3 Likes

AFAIK there is no context information of the type/module of the container (:typeinfo and :module are somewhat relevant). If you want to a brief output, I think the closest approximation may be to check :compact of IOContext and treat missing value as true:

module M

struct X
    x
end

function Base.show(io::IO, ::MIME"text/plain", x::X)
    if !get(io, :compact, true)
        print(io, "M.")
    end
    print(io, "X(")
    show(io, MIME"text/plain"(), x.x)
    print(io, ')')
end

end

then

julia> M.X(1)
X(1)

julia> [M.X(1), M.X(1)]
2-element Array{Main.M.X,1}:
 X(1)
 X(1)

I think it’s better to avoid touching show(::IO, ::T). It is called via repr and it is better if the output of repr is a valid Julia code.

Unfortunately, Julia before 1.5 calls 2-arg show via 3-arg show of containers so above method is not perfect, though.

1 Like