-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
The show docstring claims that 3-argument show(io, mime::MIME"text/plain", xs) for containers is implemented by calling show(IOContext(io, :compact=>true), mime, x) on the container elements:
julia> VERSION
v"1.7.0-DEV.706"
help?> show
...
show([io::IO = stdout], x)
...
To customize human-readable text output for objects of type T, define
show(io::IO, ::MIME"text/plain", ::T) instead. Checking the :compact IOContext
property of io in such methods is recommended, since some containers show their
elements by calling this method with :compact => true.
...
show(io::IO, mime, x)
...
Container types generally implement 3-argument show by calling show(io,
MIME"text/plain"(), x) for elements x, with :compact => true set in an IOContext
passed as the first argument.
help?> IOContext
...
IOContext(io::IO, KV::Pair...)
...
• :compact: Boolean specifying that values should be printed more compactly,
e.g. that numbers should be printed with fewer digits. This is set when
printing array elements. :compact output should not contain line breaks.
However, containers in the standard library don't follow this practice.
Vectorcallsshow()twice: firstshow(io, "text/plain", x), then, if the output contains line breaks,show(io, x);:compactis not actually set.Array{T,N}forN>1does the same, but sets:compact => true.Setcallsshow(io, x)and truncates the output to fit the display width.Dictcallsshow(io, x)with:compact => true, and also truncates the output.- Although
:compactoutput should not contain line breaks, this requirement is not respected by the containers themselves. PairandRefdon't implement 3-argumentshow().
Third-party libraries, such as DataFrames and PrettyTables, appear to use 2-argument show with :compact => true and truncate the output, pretty similar to Dict.
It seems either the show docstring or how show is implemented for standard containers should be fixed. Or, perhaps, both?
Overall, it's unclear how to properly implement show for custom types, especially containers or types with complex output layout. Perhaps, it deserves its own section in the Interfaces page of the Manual?
Aside from that, a couple of random notes:
For 2-argument show, :compact => true implies constrained horizontal space. However the role of :compact => true in 3-argument show is unclear. Is it supposed to restrict the output to a single line? Perhaps, that should be expressed with a separate context parameter?
The implementation of show for Array types can cause exponential behavior:
julia> nested(w, h) = h > 0 ? Any[nested(w, h-1) for j = 1:w] : nothing
julia> @time show(devnull, nested(6, 6))
0.006758 seconds (121.31 k allocations: 4.271 MiB)
julia> @time show(devnull, "text/plain", nested(6, 6))
6.292005 seconds (5.45 M allocations: 439.713 MiB, 0.36% gc time)
Vector and Set have identical output layouts, but print their elements very differently.
The fact that Dict truncates the output works fine for flat dictionaries, but not very convenient for JSON data.