Where is "Vector", "Matrix" printed in `typeof(::AbstractArray)`

I am looking for the code from Base that prints Vector or Matrix for a Vector or Matrix, and Array otherwise. I tried to track it down, and this seems to happen in typeof(::AbstractArray); but I can’t inspect that function, neither through which nor the debugger:

julia> [1]
1-element Vector{Int64}:
 1

julia> typeof([1])
Vector{Int64} (alias for Array{Int64, 1})

julia> @which typeof([1])
ERROR: ArgumentError: argument is not a generic function
Stacktrace:
 [1] which(f::Any, t::Any)
   @ Base .\reflection.jl:1320

How can I find this code?

(The reason I’m looking for it, is that I’m writing a custom showarg(io::IO, x::AbstractArray{<:Unitful.Quantity{T,D,U}}, toplevel). Calling nameof(typeof(x)) yields "Array", even for vectors and matrices. I currently do

    print(io, x isa Vector ? "Vector" :
              x isa Matrix ? "Matrix" :
              nameof(typeof(x)))

but that seems non-ideal (i.e. for Vector subtypes)).

1 Like

typeof() merely returns you a type, you can skip one step:

julia> Vector{Int64}
Vector{Int64} (alias for Array{Int64, 1})

the line printed out you’re seeing comes from

julia> Vector{Int64};

julia> display(Vector{Int64});
Vector{Int64} (alias for Array{Int64, 1})

(you know this is where it comes from because ; has suppressed the normal REPL display)

and I think the easiest way is:

julia> a = [1];

julia> b = [1 2];

julia> c = [1 2;;;3 4];

julia> string(typeof(a))
"Vector{Int64}"

julia> string(typeof(b))
"Matrix{Int64}"

julia> string(typeof(c))
"Array{Int64, 3}"
1 Like

display ultimately calls show(stdout, MIME("text/plain"), Vector{Int64}) as explained here. You can find the definition at:

julia> @which show(stdout, MIME("text/plain"), Vector{Int64})
show(io::IO, ::MIME{Symbol("text/plain")}, x::Type) in Base at show.jl:855

here in show.jl.

In general string(x) calls print(x), which typically calls show(io, x) (though there are some exceptions like strings that print differently). If you want the three-arg show(io, "text/plain", x) output as a string you can call repr("text/plain", x) or, most generally, sprint(show, "text/plain", x).

But it sounds like @tfiers wants the output without the type parameters but with the alias?

2 Likes

That is exact @stevengj.
We can split it off the string of course, but that’s not the cleanest.

1 Like

Vector{T} is just a alias for Array{T, 1}, the same way that Matrix{T} is a alias for Array{T, 2}.

So if you want to make a custom print for AbstractVector and AbstractMatrix subtypes you can do it like this:

function showarg(io::IO, x::AbstractArray{<:Unitful.Quantity{T,D,U}, 1}, toplevel) 
    # code for AbstractVector
end

function showarg(io::IO, x::AbstractArray{<:Unitful.Quantity{T,D,U}, 2}, toplevel) 
    # code for AbstractMatrix
end

Or;

function showarg(io::IO, x::AbstractVector{<:Unitful.Quantity{T,D,U}}, toplevel) 
    # code
end

function showarg(io::IO, x::AbstractMatrix{<:Unitful.Quantity{T,D,U}}, toplevel) 
    # code
end

Thanks for the helpfulness y’all. What a great community.

This is indeed what I’m after:

The code to print this clearly exists somewhere in the julia codebase, I just don’t know where.
I guess I’d like to see the source code of typeof(::AbstractArray).

I gave you the link above, to the show method, and you should look there to find the lower-level code for output of types. In general, how anything in Julia is displayed or printed almost always boils down to show.

1 Like

Yes, thank you. (I hadn’t actually clicked that link because I thought I knew the function it pointed to; but turned out it was a different show in Base :sweat_smile:).

Exploring that function led me to the solution:

julia> Base.make_typealias(Vector{Int})[1].name
:Vector
1 Like