# Show and showcompact on custom types

**URL:** <https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493>\
**Category:** New to Julia\
**Tags:** question, show, io\
**Created:** [January 20, 2018, 1:56pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493 "2018-01-20T13:56:04Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [January 20, 2018, 1:56pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/1 "2018-01-20T13:56:04Z")

</div>

I am trying to define a custom type with convenient methods for readout, and having some very basic trouble. I have read the documentation for show with no luck in sorting this out. Defining a method for Base.show(::IO, ::MyType) is simple enough, but when MyType is part of an array, the printout is repeated several times per instance in the array:

```julia
struct MyType
  x
end

function Base.show(io::IO, m::MyType) 
  println("instance of MyType:")
  println("x = ", m.x)
end

m = MyType(10)
M = [m, m]

```

At the console:

```julia

julia> m
instance of MyType:
x = 10

julia> M
2-element Array{MyType,1}:
instance of MyType:
x = 10
instance of MyType:
x = 10
 instance of MyType:
x = 10
instance of MyType:
x = 10

 instance of MyType:
x = 10
instance of MyType:
x = 10

```

If anyone knows the reason for this strange output, any help would be much appreciated!

One suspicion of mine is that this is somehow the result of `showcompat`, about which the [documentation](https://docs.julialang.org/en/stable/stdlib/io-network/#Base.showcompact) says: “a custom type should test get(io, :compact, false) in its normal show method”. However, I have not been able to find any examples of this in practice, and am not entirely sure what is meant by “test”.

Regardless of whether it is relevant to the problem I am experiencing, I would also like to define and use a `showcompact` method for some custom types to print nicely in arrays, and so far have not been able to find an example of that anywhere, nor another discussion topic mentioning this.

So if anyone knows the answer to these, or can point me in the right direction, I would be much obliged!

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 20, 2018, 2:09pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/2 "2018-01-20T14:09:29Z")

</div>

Eg see [this example](https://github.com/JuliaLang/julia/blob/9028130434c5fb55e00c65e73aaf13cf0afde380/base/complex.jl#L183) in `Base`, for `Complex`.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [January 20, 2018, 8:48pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/3 "2018-01-20T20:48:02Z")

</div>

Thank you!! This is exactly what I was looking for. I have looked through some of the Base code in the past but never come across that.

The result:

```julia
function Base.show(io::IO, m::MyType)
    compact = get(io, :compact, false)

    if !compact
        println("Instance of MyType:")
        print("x = ")
    end
        show(io, m.x)
end

```

```julia

julia> m = MyType(10)
Instance of MyType:
x = 10

julia> [m,m]
2-element Array{MyType,1}:
 10
 10

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 20, 2018, 8:55pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/4 "2018-01-20T20:55:51Z")

</div>

> [@tomerarnon](#):
>
> if !compact  
> println(“Instance of MyType:”)  
> print("x = ")

Normally, for multi-line display like this, you don’t use the `compact` attribute. You define a three-argument `show` method for text/plain. See the manual section on custom pretty-printing: [https://docs.julialang.org/en/stable/manual/types/#Custom-pretty-printing-1](https://docs.julialang.org/en/stable/manual/types/#Custom-pretty-printing-1)

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [January 20, 2018, 10:38pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/5 "2018-01-20T22:38:37Z")

</div>

Thanks for the reply @stevengj. I have seen that section of the docs before, but trying to implement it in the past did not produce the results I was expecting:

```julia
struct MyType
    x
    y
end

function Base.show(io::IO, m::MyType)
    compact = get(io, :compact, false)

    x = m.x
    y = m.y

    if compact
        print(x, "($y)")
    else
        print(x, " ± $y")
    end
    
end

function Base.show(io::IO, ::MIME"text/plain", m::MyType)
 
    println("Examplary instance of MyType")
    show(io, m)
    
end

```

```julia
julia> m
Examplary instance of MyType
10 ± 21

julia> [m, m]
2-element Array{MyType,1}:
10(21)10(21) 10(21)10(21)
 10(21)10(21)

```

Maybe you can shed some light as to why the array output is so garbled? I was quite surprised actually that using `if !compact` in the previous method gave me the results I was expecting, but it seemed to work. I’m probably missing something obvious here…

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 20, 2018, 10:40pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/6 "2018-01-20T22:40:16Z")

</div>

Your `show` functions need to pass `io` to `print` and `println`. Otherwise you are printing to `STDOUT`, not to the specified `io` stream.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [January 20, 2018, 10:44pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/7 "2018-01-20T22:44:21Z")

</div>

Of course! That seems to have worked now. Thanks!

In case anyone stumbles on this with the same problem:

```julia
function Base.show(io::IO, m::MyType)
    compact = get(io, :compact, false)

    x = m.x
    y = m.y

    if compact
        print(io, x, "($y)")
    else
        print(io, x, " ± $y")
    end
    
end

function Base.show(io::IO, ::MIME"text/plain", m::MyType)
    println("Examplary instance of MyType")
    show(io, m)
end

```

```julia
julia> m = MyType(10, 11)
Examplary instance of MyType
10 ± 11

julia> [m,m]
2-element Array{MyType,1}:
 10(11)
 10(11)

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 20, 2018, 10:50pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/8 "2018-01-20T22:50:27Z")

</div>

> [@tomerarnon](#):
>
> `println("Examplary instance of MyType")`

This is still missing an `io` argument.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 20, 2018, 10:52pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/9 "2018-01-20T22:52:23Z")

</div>

It seems like it would be easier to do

```julia
Base.show(io::IO, ::MIME"text/plain", m::MyType) = print(io, "Examplary instance of MyType\n", m.x, " ± ", m.y)
Base.show(io::IO, m::MyType) = print(io, m.x, '(', m.y, ')')

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [January 20, 2018, 11:00pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/10 "2018-01-20T23:00:43Z")

</div>

I see. So there’s no reason to explicitly test for compact at all if you do it this way. Thanks for the correction.

---

<div class="post-metadata">

**Author:** ![ablaom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ablaom/32/4889_2.png) [@ablaom](https://discourse.julialang.org/u/ablaom)\
**Post date:** [September 1, 2018, 12:47am UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/11 "2018-09-01T00:47:56Z")

</div>

I am writing a package where I sometimes want to display a custom type object in a markdown friendly format. In particluar, I want to record a summary of the object’s state to a .md file. For example, the object is a dictionary, and I want to display (or write it to file) as a markdown table, rather than in the usual way. Which variant of show should I be overloading to this?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [September 1, 2018, 2:30am UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/12 "2018-09-01T02:30:22Z")

</div>

> [@ablaom](#):
>
> I am writing a package where I sometimes want to display a custom type object in a markdown friendly format. … Which variant of show should I be overloading to this?

`Base.show(io::IO, ::MIME"text/markdown", m::MyType)`

---

<div class="post-metadata">

**Author:** ![ablaom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ablaom/32/4889_2.png) [@ablaom](https://discourse.julialang.org/u/ablaom)\
**Post date:** [September 1, 2018, 4:29am UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/13 "2018-09-01T04:29:27Z")

</div>

Thanks 🙂

---

<div class="post-metadata">

**Author:** ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)\
**Post date:** [December 5, 2024, 12:17pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/14 "2024-12-05T12:17:07Z")

</div>

Sorry for reviving this but I think it’s worth to add here that the `MIME` method is not called if there is no newline character in the string passed to `print`. This is new to me, although I have written hundreds of custom show methods over the past years :laughh

I am using the example above where you can see that it works (read: does what I/we think) when a newline is involved, but if `Base.show(io::IO, ::MIME"text/plain", m::MyType)` passes a single line string to `print`, the “short show” (`show(io.IO, m::MyType)`) will not be called, at least not on the REPL, when showing instances:

```julia
julia> struct MyType
         x
         y
       end

julia> MyType("hello", 42)
MyType("hello", 42)

julia> Base.show(io::IO, ::MIME"text/plain", m::MyType) = print(io, "Examplary instance of MyType\n", m.x, " ± ", m.y)

julia> Base.show(io::IO, m::MyType) = print(io, m.x, '(', m.y, ')')

julia> MyType("hello", 42)
Examplary instance of MyType
hello ± 42

julia> [MyType("hello", 42), MyType("hello", 23), MyType("hello", 1/137)]
3-element Vector{MyType}:
 hello(42)
 hello(23)
 hello(0.0072992700729927005)

julia> Base.show(io::IO, ::MIME"text/plain", m::MyType) = print(io, "Examplary instance of MyType: ", m.x, " ± ", m.y)

julia> MyType("hello", 42)
Examplary instance of MyType: hello ± 42

julia> [MyType("hello", 42), MyType("hello", 23), MyType("hello", 1/137)]
3-element Vector{MyType}:
 Examplary instance of MyType: hello ± 42
 Examplary instance of MyType: hello ± 23
 Examplary instance of MyType: hello ± 0.0072992700729927005

```

I am now playing around with the `:compact` and `:multiline` attributes of `IOContext` but I am still a little bit confused 😉

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [December 5, 2024, 1:17pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/15 "2024-12-05T13:17:12Z")

</div>

This surprised me as well, but apparently this is the intentional as discussed in

> <https://github.com/JuliaLang/julia/pull/34387#issuecomment-575311220>
>
> Triage is :+1: on this output.
> 
> A good idea from @vtjnash : first call 3-arg s…how (with compact defaulted to true, but leave it alone if already set), then check whether its output contains line breaks. If it does, try 2-arg show instead. I think that neatly handles both of my questions.

---

<div class="post-metadata">

**Author:** ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)\
**Post date:** [December 5, 2024, 1:18pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/16 "2024-12-05T13:18:35Z")

</div>

Yes, this explains a few head scratches in the past 😆

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 5, 2024, 1:44pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/17 "2024-12-05T13:44:50Z")

</div>

> [@tamasgal](#):
>
> `Base.show(io::IO, ::MIME"text/plain", m::MyType)` passes a single line string to `print`, the “short show” (`show(io.IO, m::MyType)`) will not be called, at least not on the REPL, when showing instances:

Rather than forcing yourself to include a newline, a better workaround to use 2-arg `show` when printing instances in a container is to look at the `compact` flag:

```julia
if get(io, :compact, false)
    show(io, x)
else
    # ... verbose show
end

```

in your 3-argument `show`.

As I [commented on the linked issue](https://github.com/JuliaLang/julia/pull/34387#issuecomment-2127778976) above, I dislike this change to the printing architecture, which was hacked in to modify `Date` printing. I wish we could revert it, but maybe I’m in the minority.

---

<div class="post-metadata">

**Author:** ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)\
**Post date:** [December 5, 2024, 1:48pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/18 "2024-12-05T13:48:15Z")

</div>

Thanks @stevengj, indeed I am now using the `:compact` “hack”. I hope that one is stable.

I fully agree it should be changed back.

---

<div class="post-metadata">

**Author:** ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)\
**Post date:** [December 5, 2024, 8:45pm UTC](https://discourse.julialang.org/t/show-and-showcompact-on-custom-types/8493/19 "2024-12-05T20:45:28Z")

</div>

This does not work, since `:compact` is not always set when containers are printed. For example, printing of `Vector{MyType}` does not set `:compact => true`.

Unless one looks at the stacktrace, there is currently no legal/safe/sane way to know if the printing of an element is called from the printing of a container.
