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

RFC: use IOContext more consistently. part of #14052 #16354

Merged
merged 3 commits into from
May 24, 2016
Merged

Conversation

JeffBezanson
Copy link
Sponsor Member

The whole output thing is difficult to wrap my head around, but I think I found a nice chunk to bite off.

First, showarray and showdict were undermining IOContext, so they are removed, making the IOContext flags the only thing that controls printing. That fixes e.g. #13710. It might also fix #16103 and #16267.

Second, some definitions of writemime were using it to mean "how to print in the REPL", which is not correct. Those needed to be removed in preparation for merging show and writemime. Instead I added an :interactive flag, which picks between e.g. multi-line and single-line display of vectors. REPL display is now done properly, by having the REPL print to an IOContext that sets :limit_output and :interactive.

The next steps are (1) fully merge show and writemime, (2) decide exactly which output flags we need. (2) is harder than I thought. The important variables currently seem to be:

  • Whether collections are truncated
  • Whether to use a more compact single-line format, or something better for interactive use
  • How many digits of numbers to print, and whether to use the print_shortest algorithm
  • How does summary fit in? Maybe it doesn't, and can stay a separate function.

@JeffBezanson
Copy link
Sponsor Member Author

I think this also might fix #6117, since show methods for new array types will get called now.

@JeffBezanson
Copy link
Sponsor Member Author

I see we are currently using limit_output to print shorter numbers. I don't think that's right --- it seems to me truncating containers is a different issue than how many digits to print.

@vtjnash
Copy link
Sponsor Member

vtjnash commented May 13, 2016

Biking-shedding interactive, maybe this should be pager? I'm not sure we want to encourage branching on whether the immediate display is "interactive". For example, I think Juypter may want the entire output since it implements it's own pager (aka a scrollbar).

@JeffBezanson
Copy link
Sponsor Member Author

Yeah, "interactive" may not be the right concept. We can certainly rename it.

Jupyter can still turn off limit_output though; that's orthogonal.

@nalimilan
Copy link
Member

Couldn't that interactive/pager information be obtained via displaysize? I guess a display which doesn't require wrapping lines should return (0, 0).

Regarding other variables, it seems that an important issue is whether to print type information or not. The typical use case for that is arrays which can print the type only once, and then use the most compact output possible for elements, vs. printing them individually. Cf. discussion after #14052 (comment) and #15963.

@JeffBezanson
Copy link
Sponsor Member Author

To clarify, the :interactive flag in this PR distinguishes the following 2 output formats:

julia> rand(5)
5-element Array{Float64,1}:
 0.410296 
 0.259393 
 0.0694566
 0.60467  
 0.433025 

julia> show(rand(5))
[0.46591788434697134,0.8616631147875908,0.2990903979811059,0.3327958869667973,0.04755225542278496]

@toivoh
Copy link
Contributor

toivoh commented May 14, 2016

show_unquoted passes around an indent value to be able to pretty print expressions. Perhaps this could eventually be put into IOContext? I think there's plenty more cases where indenting would be useful to make readable printouts, eg nested data structures.

@JeffBezanson
Copy link
Sponsor Member Author

@vtjnash and I were discussing that perhaps :interactive should be :multiline, to distinguish single- from multi-line ways to show data structures. This seems like a useful distinction to have.

@JeffBezanson JeffBezanson force-pushed the jb/output branch 2 times, most recently from 1851ede to 08a2841 Compare May 20, 2016 03:22
@JeffBezanson
Copy link
Sponsor Member Author

Ok, I think things are pretty clean here now. I used the following 3 output flags:

  • limit: Omit elements of big containers
  • compact: Print numbers with fewer digits
  • multiline: Request interactive-style long-form output, otherwise try to keep output on a single line

showcompact now only has one definition, which just sets compact to true. All types define only show (and summary).

The flags are used in several ways. For example, array elements are always printed with multiline=false, but compact=true is set only if the io object doesn't already have a setting for compact. This lets you get many combinations of output options from the repl by calling show with an appropriate IOContext.

@@ -93,7 +93,7 @@ macro enum(T,syms...)
end
end
function Base.show(io::IO,x::$(esc(typename)))
if Base.limit_output(io)
if get(io, :compact, false)
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had been writing these as get(io, :compact, false) === true for future-compatibility / robustness against bad IOContext settings. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather get an error when a non-Bool is passed in the IOContext than a silent fallback to false. This makes it easier to detect mistakes.

@nalimilan
Copy link
Member

+1 for multiline.

Though don't we want another flag to set the amount of information to print (and not only number of digits)? Cf. my comment above. @JeffBezanson, you said at #15454 (comment) that you wanted to support several verbosity levels, which was needed for enums printing (but also e.g. for Nullable). Is that still needed?

@JeffBezanson
Copy link
Sponsor Member Author

I think it turns out that most verbosity issues need to be factored into separate flags. I don't have a concrete proposal for a verbosity enum, but we can discuss if somebody puts one forward.

@JeffBezanson
Copy link
Sponsor Member Author

Ok this should be in pretty good shape now.

@kmsquire
Copy link
Member

@vtjnash https://github.com/vtjnash & I just came to the conclusion
that IOContext is not really the right tool for detailed number formatting.
If you need to control the number of digits, you need something like printf.

For matrix/vector display, having the ability to format all
entries similarly would be nice. Why wouldn't IOContext be good for this?

@vtjnash
Copy link
Sponsor Member

vtjnash commented May 21, 2016

fix #16026
fix #15454

@JeffBezanson
Copy link
Sponsor Member Author

having the ability to format all entries similarly would be nice

Yes, this can be debated. Let's focus on just the changes in this PR first.

@tkelman
Copy link
Contributor

tkelman commented May 23, 2016

travis osx failure log backed up to https://gist.github.com/3cd64fa498b4defbd9a9d72198ddf477, restarted

We had several `writemime` definitions whose purpose was to control how
objects should be printed in the REPL. Instead this introduces a
`:multiline` IOContext flag.

Use `:compact` IOContext flag to request shorter printing of numbers.

Removes `showarray` and `showdict`, allowing IOContext flags to work
better recursively. Fixes #13710.

Also related: #16103 and #16267.
@tkelman
Copy link
Contributor

tkelman commented May 23, 2016

Should showcompact_lim have a deprecation added in case any packages were using it? The deprecation for with_output_limit still doesn't appear to do any limiting.

@JeffBezanson
Copy link
Sponsor Member Author

JeffBezanson commented May 24, 2016

with_output_limit is incompatible with the way this works now. The API is get(io, :limit, default), so you either get the setting from io or default, and there's nowhere to use the global variable. If the deprecation was made to work, then behavior of code using the new API would change when the deprecation is removed. That didn't seem like a good tradeoff to me for a non-exported function.

EDIT: It can mostly work if the global flag is 3-valued.

@JeffBezanson
Copy link
Sponsor Member Author

I will merge this after CI. showcompact_lim has been around a pretty short time, but if it turns out to have users we can add a deprecation later.

@JeffBezanson
Copy link
Sponsor Member Author

That AV timeout again.

@nalimilan
Copy link
Member

FWIW, this (combined with previous PRs) allowed getting rid of about 300 lines of custom printing methods in NullableArrays.jl. Now everything works fine with the default AbstractArray methods!

@tkelman
Copy link
Contributor

tkelman commented May 25, 2016

BlockArrays, CSV, DataStreams, and TypedTables were all using showcompact_lim. Possibly more being obscured by existing failures on 0.5. http://pkg.julialang.org/pulse.html

jrevels added a commit to JuliaCI/BenchmarkTools.jl that referenced this pull request May 26, 2016
jrevels added a commit to JuliaCI/BenchmarkTools.jl that referenced this pull request May 30, 2016
@@ -57,31 +57,33 @@ mimewritable(m::AbstractString, x) = mimewritable(MIME(m), x)
# format and is returned unmodified. This is useful so that raw data can be
# passed to display(m::MIME, x).

verbose_writemime(io, m, x) = writemime(IOContext(io,multiline=true,limit=false), m, x)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this led to JuliaLang/IJulia.jl#462

It's not a big deal; in hindsight, I'm not sure the whole stringmime function belongs in Base anyway. It should be easy enough to implement a limitstringmime in IJulia.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dict display differences between 0.4 and 0.5
8 participants