Approaches to store a `MIME` type *with* a regular `String` for show() et'al?

I found using multiple dispatch with show(io::IO, ::MIME"text/plain", ::T) quite handy. This seems to work like magic – that is, if you have your own types for show()'s dispatch. But if ::T arrives at show() as String, it’s handled as plain/text. So not sure the best way to “subclass” an AbstractString to store it’s MIME type, while still acting like a String type downstream.

I deal with HTTP stuff a lot. So keep running into is I have some MIME content that is represented as a basic String type in Julia code, say JS, HTML, etc. Since the code knows the string’s MIME type at creation, I want to preserve it with as an AbstractString – but still dispatch on based on the AbstractString & some “stored” MIME type.

For some of my types I have a show() that convert that type to a DataFrame and then re-call show() again with the DF as param. Since DataFrame-based things have show/print/display (& vscodedisplay()) helpers already, this works well in REPL and Pluto.jl.

My problem is solvable by creating a bunch a “struct wrappers” for what is just a String with a known MIME type at an intermediate step in the code. Often the stop at show() (and it’s ilk) are transitorily, before later processing – so creating types solely for use with show() while coding/debugging seems ugly.

The most recurring one for me is JSON – I know the String variable contains JSON, but may not want to pass around DataFrames (or other Type) elsewhere in my code for the sole reason to have something so a [external] call to show() works correctly – even though that’s useful. Basically, many existing functions expect a AbstractString, but still like the some clean way to “store” it’s MIME type while still acting like some kinda AbstractString – but couldn’t find anything in stdlib/Base thing that did this.

Obviously not a showstopper here. Still learning Julia, so mainly a “design patterns” questions. But curious if anyone had any thoughts.

This is exactly how it’s usually solved in Julia. If you want to change the dispatch, you need to change the type. e.g. there is a type HTML built-in that wraps a string s as HTML(s) to tell the display backend the render it as HTML if possible.

That being said, you can manually call display("text/html", some_string) to render some string as HTML (if the display backend supports HTML rendering, of course), and similarly for other MIME types.

Well, you can also define a subtype of AbstractString that has additional show methods for rich display, see e.g. LaTeXStrings.jl for an AbstractString subtype that renders as text/latex (on displays that support LaTeX math).

3 Likes

But I want to cheat the declarative types ;). Although I’m a bit surprised there is not a macro that fills in the “abstract methods” for at least something basic like AbstractString (e.g. a string). While I get there aren’t actually any “default methods” in an abstract – but even the typical ones seemed illusive.

So thanks for your src/LaTeXStrings.jl example – I’d imagine a LaTeXString would run into most of methods needed.

Yeah that totally does work. But it was actually the seemingly “extraneous” calls to display(::MIME, ::AbstractString) from the REPL that I wanted to avoid somehow – I like x |> display syntax too much :wink:

I think I was hoping for some magic “typed string” (e.g. act like a sting everywhere, but had it’s own type) – e.g. without having to write all dispatches for AbstractString in my code & somehow cheating the “all concrete types are final” rule. Lucky Julia has macros.

Thanks!

P.S. by “methods”, I mean “functions” :wink:

there is, Docstrings · Lazy.jl

Yup the @> and @as macros are what I was missing in Julia.

|> was limiting, I just didn’t know it.