Improving doc for display/print/show/repr/

Continuing on what was started in (wrong forum?) Julep: extended proposal for fixing show, print, & friends · Issue #14052 · JuliaLang/julia · GitHub

Questions

  • Why would we use repr() over string()?
    • Clearly, the call stack is different (sprint vs print_to_string) — but I can’t figure out why.
  • Why does print() drop ::MIME in the print layer — instead of delegating that choice to the show layer?

A little background information

Peering into the display/print/show system

Using the following to probe into specific call stacks:

Base.show(io::IO, o::SomeObj) = throw("Dump Call Stack: No MIME")
#Base.show(io::IO, ::MIME"text/plain", o::SomeObj) = throw("Dump Call Stack: MIME")

Observations: Julia print/display system

show() call stacks

show(::SomeObj) -> show(::IO, ::SomeObj)
show(::MIME, ::SomeObj) -> NO IMPLEMENTATION! (that's fine; ::IO is simply required)
show(::IO, ::MIME, ::SomeObj) -> show(::IO, ::SomeObj) #Default behaviour

NOTE:

  • Might want to implement show(::IO, ::MIME"text/plain", ::SomeObj) for pretty printing

print() call stacks

print(::SomeObj) -> print(::IO, ::SomeObj) -> show(::IO, ::SomeObj)
print(::MIME, ::SomeObj) -> print(stdout::IO, ::MIME, ::SomeObj) -> print(::IO, ::SomeObj) -> show(::IO, ::SomeObj)
print(::IO, s::STRING) -> write(::IO, s) #BYPASS SHOW COMPLETELY FOR STRINGS

NOTE:

  • Doesn’t use show(::IO, ::MIME"text/plain", ::SomeObj) for pretty printing (even if ::MIME is specified).

WARNING: The following statements do not work in an orthogonal way:

  • print(MIME("text/plain"), "SomeString")
  • print(stdout, MIME("text/plain"), "SomeString")

They print the ::MIME, then the ::String. They do not use ::MIME to specialize formatting of print().

repr() call stacks

repr(::SomeObj; context) -> sprint(::Function{show}, ::SomeObj; context) -> show(::IO, :SomeObj)
repr(::MIME, ::SomeObj; context) -> show(::IO, ::MIME, ::SomeObj) -> show(::IO, ::SomeObj)

NOTE:

  • Uses show(::IO, ::MIME"text/plain", ::SomeObj) for pretty printing if ::MIME is provided.

string() call stacks

string(::SomeObj) -> print_to_string(::SomeObj) -> print(::IO, ::SomeObj) -> show(::IO, ::SomeObj)
string(::MIME, ::SomeObj) -> print_to_string(::MIME, ::Vararg) -> print(::IO, ::SomeObj) -> show(::IO, ::SomeObj)

NOTE:

  • Doesn’t use show(::IO, ::MIME"text/plain", ::SomeObj) for pretty printing (even if ::MIME is specified).

display() call stacks

With a TextDisplay <: Base.AbstractDisplay @ top of display stack (see pushdisplay()):

display(::SomeObj) -> display(::TextDisplay, ::SomeObj) -> display(::TextDisplay, ::MIME"text/plain", ::SomeObj)

Which would typically then call an appropriate MIME-aware show() function, for example:

show(::IO, ::MIME"text/plain", ::SomeObj) -> show(::IO, ::SomeObj) #Default fallback

NOTE:

  • Thus, a user-defined type should explicitly define said MIME-aware show() function for “pretty-printing”:
    • show(::IO, ::MIME"text/plain", ::SomeObj)
  • Fancier displays (ex: Jupyter notebooks) might support richer ::MIME formats by calling specialized methods, for example:
    • show(::IO, ::MIME"text/html", ::SomeObj)
    • show(::IO, ::MIME"image/png", ::SomeObj)
    • (Specialized methods are typically implemented by the package defining ::SomeObj)

User-defined AbstractDisplays

With a user-defined CustomDisplay <: Base.AbstractDisplay @ top of display stack:

display(::SomeObj) -> display(::CustomDisplay, ::SomeObj) #NO DEFAULT IMPLEMENTATION

Thus, to work with display() system, user must implement custom:

  • display(::CustomDisplay, ::Any)
  • and/or display(::CustomDisplay, ::SomeObj)

WARNING:

  • display(::SomeObj) never to be implemented directly for risk of breaking display() system.
1 Like

I agree some work is still needed in this area.

The difference between repr("a") == "\"a\"" and string("a") == "a" seems right to me.

However, as I wrote in Distinguish string functions for data values vs programmer information · Issue #40779 · JuliaLang/julia · GitHub I do think there remains some issues here — though it may be necessary to wait till 2.0 to fix them. In particular, the idea of “printing the value itself” seems inapplicable to most types and usages of print(x) and string(x) are likely to be bugs for those types – the exceptions being String, Int, and some others.