Julia: Provide a simple way to print all entries in a collection

Created on 17 Sep 2018  路  8Comments  路  Source: JuliaLang/julia

There is currently no simple way to print all entries in a collection (in particular in a vector) in a readable way. For example, if one wants to get all the column names in a table/data frame. show(x) prints a vector in full, but the entries are not aligned, making it quite painful to read on most terminals:

julia> show(string.("col", 1:50))
["col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9", "col10", "
col11", "col12", "col13", "col14", "col15", "col16", "col17", "col18", "col19", "co
l20", "col21", "col22", "col23", "col24", "col25", "col26", "col27", "col28", "col2
9", "col30", "col31", "col32", "col33", "col34", "col35", "col36", "col37", "col38"
, "col39", "col40", "col41", "col42", "col43", "col44", "col45", "col46", "col47", 
"col48", "col49", "col50"]

Currently the only way to print all entries in a vertical layout is show(stdout, "text/plain", x). It works well, but telling newcomers to write this just to see the list of columns in their table isn't terribly convincing, and it's very hard to discover.

Can we do something about this? Intuitively I would have expected show(x) to be equivalent to show(stdout, "text/plain", x) (and have print(x) do what show(x) currently does), but it's kind of late to change this. Should we introduce a new convenience function, or a standardized keyword argument?

FWIW, this issue also exists e.g. with DataFrames, where we support a few keyword arguments to easily decide whether to print all rows/columns (https://github.com/JuliaData/DataFrames.jl/pull/1506).

display and printing

Most helpful comment

I'd like to emphasis that the current solution (show(stdout, "text/plain", x)) is _very hard_ to discover in the manual.

A typical reading flow trough the manual may look like this:
1) You read about pretty printing of types and learn how show works (https://docs.julialang.org/en/v1/manual/types/#man-custom-pretty-printing-1)
2) you jump to Multimedia IO and read more about show (https://docs.julialang.org/en/v1/base/io-network/#Base.show-Tuple{Any,Any,Any}). You learn that
"The default MIME type is MIME"text/plain". There is a fallback definition for text/plain output that calls show with 2 arguments. Therefore, this case should be handled by defining a 2-argument show(io::IO, x::MyType) method."
This is very confusion because it sounds as if show(io::IO, x::MyType) and show(stdout, "text/plain", x) are the same function.
4) You learn about IOContext (https://docs.julialang.org/en/v1/base/io-network/#Base.IOContext-Tuple{IO,Pair}) and try show(IOContext(stdout, :limit => false), x) which is close but still not the solution
5) you give up or google to find this issue :)

All 8 comments

showall ? :trollface:

Maybe we should try to add some simple line break logic?

showall ? :trollface:

Yeah, that would be ironic, but why not. https://github.com/JuliaLang/julia/pull/22847 said "This function has become pretty useless, since showing everything is basically the default." That's right, except for interactive use at the REPL. It wouldn't be totally absurd to me to have the convenience function showall(io, x) = show(IOContext(io, :limit => false), x). Or we could add varargs to show, to allow passing context properties in a concise way.

Maybe we should try to add some simple line break logic?

What do you mean?

BTW, another context where one often needs to list names or entries is when looking at BenchmarkTools results (which is currently buggy, see https://github.com/JuliaCI/BenchmarkTools.jl/issues/96).

Actually, I realize the problem with the old showall is that it didn't allow reproducing vertical layout of the REPL output, just adding :limit=>false. What's needed for that is show(IOContext(io, :limit=>false), "text/plain", x). So it was indeed essentially equivalent to show, print and repr.

Maybe we should try to add some simple line break logic?

What do you mean?

Making the entries line up better.

So that means making show(io, x::AbstractArray) significantly different from print(io, x)? That wouldn't be absurd, but currently the manual says that show(io, x) is for single-line representation.

Currently the only way to print all entries in a vertical layout is show(stdout, "text/plain", x)

You can also do println.(x);

I'd like to emphasis that the current solution (show(stdout, "text/plain", x)) is _very hard_ to discover in the manual.

A typical reading flow trough the manual may look like this:
1) You read about pretty printing of types and learn how show works (https://docs.julialang.org/en/v1/manual/types/#man-custom-pretty-printing-1)
2) you jump to Multimedia IO and read more about show (https://docs.julialang.org/en/v1/base/io-network/#Base.show-Tuple{Any,Any,Any}). You learn that
"The default MIME type is MIME"text/plain". There is a fallback definition for text/plain output that calls show with 2 arguments. Therefore, this case should be handled by defining a 2-argument show(io::IO, x::MyType) method."
This is very confusion because it sounds as if show(io::IO, x::MyType) and show(stdout, "text/plain", x) are the same function.
4) You learn about IOContext (https://docs.julialang.org/en/v1/base/io-network/#Base.IOContext-Tuple{IO,Pair}) and try show(IOContext(stdout, :limit => false), x) which is close but still not the solution
5) you give up or google to find this issue :)

Currently the only way to print all entries in a vertical layout is show(stdout, "text/plain", x)

You can also do println.(x);

println.(x); doesn't work well with NamedArray effectively deleting the names. show(stdout, "text/plain", x) doesn't work well with arrays of length 20 either. The only solution for those cases is show(IOContext(stdout, :limit => false), x)

You can play with this example:

#Create named array
x = NamedArray([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
                            (["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"],))

println.(x)  #works but deletes names
show(stdout, "text/plain", x)     #jumps from 7 to 14 missing the middle
show(IOContext(stdout, :limit => false), x) #works showing everything
Was this page helpful?
0 / 5 - 0 ratings