Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show, showcompact, showall, showlimited, print, repr, summary, and friends #5709

Closed
mbauman opened this issue Feb 7, 2014 · 15 comments
Closed
Labels
domain:display and printing Aesthetics and correctness of printed representations of objects. domain:docs This change adds or pertains to documentation

Comments

@mbauman
Copy link
Sponsor Member

mbauman commented Feb 7, 2014

In creating PR #5706 I had some trouble in figuring out what all the different flavors of show do. There seems to be some consensus on what information should be displayed when pretty-printing types, often like:

TypeInformation and some metadata here:
  (with the data expressed here)

But how this happens, and, more importantly, how output is limited seems to be somewhat haphazard. In turn, it's hard for users to determine which functions should be implemented for their types — it took me a long time to realize that showcompact is orthogonal to showlimited (the former does things like shortening floating point precision while the latter omits elements, if I now understand correctly.)

I searched through the issues and while there's some smattering of discussion about specific datatypes and there are some todo notes in the code but I thought there might be some value in looking at the overall architecture. With IJulia and REPL.jl around the corner, it might be nice to standardize some of these functions. I'm sure @tknopp will have some thoughts here as he implements his workspace browser.

As I see it, there are two or three different feature sets that are important for writing to MIME"text/plain":

  • Printing with full or limited precision
  • Printing with full or limited number of rows and columns
  • Printing with or without summary information

Of course, what makes this difficult is that in the implementation, you generally only want to use one function with minor adjustments. Would the situation be improved with just one show API along the lines of the amazing showarray (albeit without keyword arguments)?

function showarray(io::IO, X::AbstractArray,
                   header::Bool=true, limit::Bool=_limit_output,
                   rows = tty_rows()-4, cols = tty_cols())

Users could choose to ignore the final arguments and multiple dispatch could be setup to ignore them if users only defined it in terms of the first two arguments. This is just a spitball to get the discussion rolling… is there interest in doing something here?

@tknopp
Copy link
Contributor

tknopp commented Feb 7, 2014

Wow, I was not even aware of showlimited and showarray.

It seems that showarray has the right signature but should be there for any type. Further, and this is very essential for my application is that the repr function is adapted in the same way.

When this is available I can implement a Text Widget that automatically adapt its content while resizing.

@mbauman
Copy link
Sponsor Member Author

mbauman commented Feb 7, 2014

Of course, the limited and array flavors of show aren't exported (and as such aren't documented). But since the current repl uses showlimited to display objects to text/plain, it's what I've been using (along with show) to implement my types.

I realized that my spitballed proposal wouldn't work; you'd want to magically dispatch both ways depending on if you're wanting to simplify writing or using the API.

Currently, display (for text/plain) calls writemime which falls back to showlimited which falls back to show. What if a new showcomplete was the showarray-like function? Then we could simplify this chain:

writemime(io, ::MIME"text/plain", x) -> show(io::IO, x) -> showcomplete(io::IO,x,… all the default argument flags …)

And then the default implementation for showing unspecialized datatypes (e.g., what is currently show(io::IO, x::ANY) at show.jl:8) would be instead implemented at showcomplete(…) with the full signature.

Users writing new types could quickly get a simple display up quickly, but it also allows for a simple way to latch into full-functionality. And show(x) would still just work. I had initially thought about using print as the name for showcomplete, but it'd be hard to deprecate, I think. And this way the repr API could nicely mirror this.

(I'm still just getting into Julia… let me know if I'm overstepping any bounds here)

@JeffBezanson
Copy link
Sponsor Member

You're right that show is basically the core function: showall, showlimited, etc. are wrappers that call show in a different way. The big problem is how to get the extra parameters into show methods. Right now we use a global variable.

It looks like showcompact and summary could be combined into one thing, which might just call show with compact=true.

repr is just showall to a string, so it can be left alone. Only a few types need custom print methods, and print also doesn't need all the extra parameters, so it is easy as well.

@tknopp
Copy link
Contributor

tknopp commented Feb 8, 2014

Ok, but is it currently possible to get a limited string representation of any type (or at least for arrays) that does not print the result?

@JeffBezanson
Copy link
Sponsor Member

You can get the output of printing functions with sprint.

@tknopp
Copy link
Contributor

tknopp commented Feb 8, 2014

Wow, this is great thanks

@mbauman
Copy link
Sponsor Member Author

mbauman commented Feb 19, 2014

I suppose I should be more specific in outlining what I'd like show to support, and why I think it'd be worth refactoring all these various show* methods. Here's a concrete example: I think that the default printing of user types could be improved greatly. Given some composite type:

type MyType{T<:String,S<:Number}
    name::T
    data::Array{S,2}
    dict::Dict
end

It'd be absolutely amazing to have something like this out of the box:

julia> x = MyType("a very long name. "^10, rand(50,2), Dict(1:100,map(string,1:100)))
MyType{ASCIIString,Float64}:
  name:  ASCIIString: "a very long name. a very long name. a very long name…
  data:  10x2 Array{Float64,2}: [0.144676  0.515512; 0.892452  0.967434; 0.…
  dict:  Dict{Int64,ASCIIString} with 100 entries: [5=>"5",56=>"56",35=>"35…
julia> x.name
ASCIIString:
 "a very long name. a very long name. a very long name. a very long name. a 
very long name. a very long name. a very long name. a very long name. a very
 long name. a very long name. "
julia> x.data
# prints the array, abbreviated as usual
julia> x.dict
Dict{Int,ASCIIString} with 100 key-value pairs:
  5 => "5"
  56 => "56"
  35 => "35"
     ⋮

Now, to get this sort of effect currently, you have to ask for a larger representation than what is needed and search for newlines. And since there's no consistency in what summary information is shown, you can't be clever about omitting it if the values are all the same concrete type.

I started work on adding variable keyword parameters to all show methods, and then selectively asking for the specific ones that different methods care about. But it's a pain that all show methods must have ; kw... at the end of its argument list to work at all. So I don't know if that would be a reasonable solution.

@mbauman
Copy link
Sponsor Member Author

mbauman commented Mar 12, 2014

Also related are issues #25 (for unspecialized types) and #4163 (for dump and xdump).

simonster added a commit that referenced this issue Jun 19, 2014
Ref #7297

We really need a better solution for this generally (see #4117/#5709)
but I suppose reinstating `ENV` as fallback is easy for now.
@quinnj
Copy link
Member

quinnj commented Jul 2, 2014

Also related #6269

@tkelman
Copy link
Contributor

tkelman commented Sep 23, 2015

Significant refactoring is unlikely on release-0.4, removing from 0.4.x milestone.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Mar 25, 2016

see #14052 proposal for latest cleanup plans

@JeffBezanson
Copy link
Sponsor Member

As discussed elsewhere: we need to add an enum to express the available verbosity levels.

@JeffBezanson JeffBezanson added the domain:docs This change adds or pertains to documentation label May 24, 2016
@JeffBezanson
Copy link
Sponsor Member

Converted to a doc issue to explain how the output system works more.

@JeffBezanson JeffBezanson added the domain:display and printing Aesthetics and correctness of printed representations of objects. label Jan 3, 2017
@nalimilan
Copy link
Member

Can we close this now?

@mbauman
Copy link
Sponsor Member Author

mbauman commented May 29, 2020

We no longer have showcompact, showall, or showlimited. print and summary are well-defined and simple enough. display is for more than just IOs, but uses show for its contents.

repr is still a little funny (it's documented to effectively just be sprint(show, x) and not worth overriding). It might be worth getting rid of it in 2.0 as its name gives me the misconception that it's a fully parseable and round-trippable output. But that's #33260.

show itself has gone through multiple revisions and documentation overhauls, now supporting MIME types, IOContexts, and such that get to the root of the original issue. I think this issue can be closed (especially with the further improvements in #36076, but it's already progressed far enough to close this issue).

@mbauman mbauman closed this as completed May 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:display and printing Aesthetics and correctness of printed representations of objects. domain:docs This change adds or pertains to documentation
Projects
None yet
Development

No branches or pull requests

7 participants