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(io, x) vs show(io, "text/plain", x) -- docs? #18004

Open
stevengj opened this issue Aug 12, 2016 · 12 comments
Open

show(io, x) vs show(io, "text/plain", x) -- docs? #18004

stevengj opened this issue Aug 12, 2016 · 12 comments
Assignees
Labels
display and printing Aesthetics and correctness of printed representations of objects. docs This change adds or pertains to documentation

Comments

@stevengj
Copy link
Member

The manual states that since the default show(io, "text/plain", x) calls through to show(io, x), all you ever have to define is the latter. However, this doesn't seem to be quite true.

In particular, the REPL calls display(x) which calls show(io, "text/plain", x), not show(io, x), and the array display exploits this to output a "2d" representation of a matrix in the REPL by calling showarray(io, x, false) from show(io, "text/plain", x), whereas it separately overloads show(io, x) to call showarray(io, x, true) and get a "1d" representation of a matrix for print and friends.

This trick is not documented, and seems contrary to the spirit of #14052. Maybe display should call show(IOContext(io, someattribute=true), "text/plain", x) for some attribute that indicates that a "display" version of x is desired?

cc @vtjnash

@stevengj stevengj added the io Involving the I/O subsystem: libuv, read, write, etc. label Aug 12, 2016
@JeffBezanson
Copy link
Member

We did it that way originally; the attribute was called multiline. Was changed by #17113

@Evizero
Copy link
Contributor

Evizero commented Aug 13, 2016

aha! I did run into this a couple of times and was kinda confused what I was doing wrong (I am confused easily). Not complaining here though, never was a serious issue for what I was trying to do. Just confirming that some people do indeed run into this in practice

@stevengj stevengj added the docs This change adds or pertains to documentation label Aug 13, 2016
@stevengj stevengj changed the title show(io, x) vs show(io, "text/plain", x) -- need REPL IO attribute? show(io, x) vs show(io, "text/plain", x) -- docs? Aug 13, 2016
@stevengj
Copy link
Member Author

Okay, maybe it just needs to be documented, then?

@vtjnash vtjnash self-assigned this Sep 11, 2016
@JeffBezanson JeffBezanson added display and printing Aesthetics and correctness of printed representations of objects. and removed io Involving the I/O subsystem: libuv, read, write, etc. labels Jan 3, 2017
@nalimilan
Copy link
Member

The situation has changed a bit since this issue was filed, but the problem remains. What has changed is that we now have a fallback:

show(io::IO, ::MIME"text/plain", x) = show(io, x)

Yet, the manual still recommends overloading the two-argument show(io, x) method for single-line printing, but the three-argument show(stdout, MIME("text/plain"), x) method for multiline printing:

sometimes one wants both a verbose multi-line printing format, used for displaying a single object in the REPL and other interactive environments, and also a more compact single-line format used for print or for displaying the object as part of another object (e.g. in an array). Although by default the show(io, z) function is called in both cases, you can define a different multi-line format for displaying an object by overloading a three-argument form of show that takes the text/plain MIME type as its second argument (see Multimedia I/O).
Technically, the REPL calls display(z) to display the result of executing a line, which defaults to show(stdout, MIME("text/plain"), z), which in turn defaults to show(stdout, z), but you should not define new display methods unless you are defining a new multimedia display handler (see Multimedia I/O).

I find this approach confusing given that it parallels the IOContext system which is used to control other aspects of printing. To make this more systematic, I suggest we reintroduce a :multiline IOContext property which can be checked just like other properties in any show method, be it for text/plain or for any other format.

The argument against this which justified the removal of the :multiline property in #17113 was that it doesn't nest automatically: an array will use multi-line printing, but its elements should each take a single line. But I don't see the problem: containers can just pass :multiline => false when printing their elements, just like they typically pass :compact => true and typeinfo => eltype(c). Non-container types (the majority) don't have to bother. Yes, it will require some adjustments to set :multiline => false in places where we could just call show(io, x), but that doesn't seem to be a big problem.

I think that using an IOContext property is more compelling now that we have cleaned up the printing machinery and deprecated showcompact in favor of it (#26080). Now can potentially simplify it around only two concepts: the display MIME format, and IOContext properties. That also allows choosing single-line or multi-line display for formats other than text/plain, which is currently impossible. At the time when #17113 was merged, we didn't have a completely clear system so it made sense to apply a practical fix to avoid regressions. We can probably do better now.

@nalimilan nalimilan added the triage This should be discussed on a triage call label Mar 11, 2018
@stevengj
Copy link
Member Author

Almost all user types are containers for other types. This means that multiline=false will potentially have to be set in a huge number of places.

In fact, arguably all calls to print (which currently calls the 2-argument show) should set multiline to false, which would mean that every print call would introduce the overhead of constructing an IOContext.

@vtjnash
Copy link
Member

vtjnash commented Mar 11, 2018

Correct, that is why :multiline was a bit of a mess. It wasn't obvious though until we had tried it for a few months. I try to explain it as a "text/plain" formatted document being different from string formatting – which isn't quite obvious, but the difference being also that layout can only be applied at the outer-most level & shouldn't try to apply recursively. This is precisely what MIME means, while IOContext means parameters that are valid for all recursive consumers to use – or ignore (it's never correct to expect to override them).

@JeffBezanson
Copy link
Member

I would also prefer not to flip-flop on this. In practice, this would have the effect of expanding 2 forms of show to 4, which will not be as much of a net improvement as we'd like.

@nalimilan
Copy link
Member

OK. So that means we consider that the multi-line/single-line distinction doesn't make sense for formats other than plain text? Or maybe the difference between the two-argument and the three-argument show methods isn't single vs. multiple lines, but rather "Julia syntax-like" vs. custom pretty output?

@vtjnash
Copy link
Member

vtjnash commented Mar 13, 2018

No, there's nothing particularly special about plain-text output, other than (like the "text/plain" mime type) being the default (and, specifically, to output utf8-encoded content). I created an example of an HTML stream (text/html mime type) as part of my research during creation of the IOContext concept (https://github.com/JuliaLang/julia/compare/jn/iocolor#diff-c20eb2eead14027fab4293e10bacf73bR398). The difference as actually more obvious with complex formats, where two-arg show renders only a portion of a document (such as some HTML formatting tags), while three-arg show is expected to render a completed document (such as adding <head/><body/>).

@JeffBezanson JeffBezanson removed the triage This should be discussed on a triage call label Mar 13, 2018
@nalimilan
Copy link
Member

Sorry, I don't really understand your example. What I meant is that there's no way to request printing a custom type using a single or multiple lines in the text/html output format since there's no IOContext property for that. Since we use the distinction between the two-argument and three-argument methods to decide whether to use multiple lines or not, all formats other than the two-argument default can only be multiline.

@JeffBezanson
Copy link
Member

Correct; there is no such thing as requesting multi-line output. What we have instead is methods with a MIME type, and those without.

@nalimilan
Copy link
Member

Then can we find better guidelines regarding what kind of output the method without a MIME type should produce compared to those with a MIME type? As I noted above, the manual still mentions multi-line output as a difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
display and printing Aesthetics and correctness of printed representations of objects. docs This change adds or pertains to documentation
Projects
None yet
Development

No branches or pull requests

5 participants