Short-form printing not working in vectors

I’m trying to define short-form and long-form printing for a custom type. It seems to work as expected except when I put objects of the custom type in a vector. Here’s the code:

struct Foo
    x::Int
    y::Int
end

function Base.show(io::IO, ::MIME"text/plain", f::Foo)
    print(io, "Foo: {", f.x, ", ", f.y, "}")
end

function Base.show(io::IO, f::Foo)
    print(io, "{", f.x, ", ", f.y, "}")
end

Long-form printing works:

julia> Foo(1, 2)
Foo: {1, 2}

And short-form printing works in a tuple or pair:

julia> (Foo(1, 2), Foo(3, 4))
({1, 2}, {3, 4})

julia> Foo(1, 2) => Foo(3, 4)
{1, 2} => {3, 4}

But short-form printing is not working in a vector:

julia> [Foo(1, 2), Foo(3, 4)]
2-element Vector{Foo}:
 Foo: {1, 2}
 Foo: {3, 4}

Does anyone know what is going on here? I thought that vector printing is supposed to use the short-form, as the example in the manual shows.

(Code tested on v1.8.2)

julia> VERSION
v"1.8.2"

The short form is used with print or println for a vector:

julia> println([Foo(1, 2), Foo(3, 4)])
Foo[{1, 2}, {3, 4}

I dunno, the example in the manual works as expected in the REPL without calling print or println on the vector:

julia> Polar(3, 4.0)
Polar{Float64} complex number:
   3.0 * exp(4.0im)

julia> [Polar(3, 4.0), Polar(4.0,5.3)]
2-element Vector{Polar{Float64}}:
 3.0 * exp(4.0im)
 4.0 * exp(5.3im)

The only difference I can see between my example and the example in the manual is that my long-form version only prints one line, whereas in the example in the manual the long form prints multiple lines. However, I really wouldn’t think that that would affect which show method on Foo is getting called when I print a vector of Foo.

1 Like

What would be the workaround here?

Would something like this be alright:

function Base.show(io::IO, ::MIME"text/plain", v::Vector{Foo})
  println("$(length(v))-element $(typeof(v))")
  foreach(f->println(io, f), v)
end

julia> [Foo(1, 2), Foo(3, 4)]
2-element Vector{Foo}
{1, 2}
{3, 4}

I was hoping somebody would point out something subtle that I’m doing wrong. :slight_smile:

Or if it’s actually a bug, then I should file a github issue.

But that’s exactly it; if the 3-argument show makes a one-liner, it’s used for arrays too. The logic is in Base.print_matrix_row().

1 Like

Aw, shucks. I had hoped that the array printing was based purely on dispatching the 2-argument show, rather than checking the 3-argument show output for a newline character. Basing the printing on dispatch would be a lot more predictable. In fact, the manual strongly implies that the 2-argument show is called when printing array elements:

In particular, 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).

This results in: […] where the single-line show(io, z) form is still used for an array of Polar values.

3 Likes