Get type of field in parametric type

Let’s say I have a parametric type defined as

mutable struct Example{T,N<:Real}
  a::T
  b::Array{N,1}
end

I can create an object with something like,

x = Example(:a, [1, 2, 3])

Then the type of x is Example{Symbol, Int64} – is there a way to get Int64? So far I found

eltype(fieldtype(typeof(x), 2))

which works, but I was wondering whether there is a more julianesque way of getting the same result?

2 Likes
Base.@pure get_type_parameter(x) = typeof(x).parameters[2]

That infers.

julia> Base.@pure get_type_parameter(x) = typeof(x).parameters[2]
get_type_parameter (generic function with 2 methods)

julia> @code_warntype get_type_parameter(rand(3))
Variables:
  #self# <optimized out>
  x <optimized out>

Body:
  begin
      return $(Expr(:invoke, MethodInstance for getindex(::SimpleVector, ::Int64), :(Main.getindex), :((Core.getfield)(Array{Float64,1}, :parameters)::SimpleVector), 2))
  end::Int64

The more general form

Base.@pure get_type_parameter(x,i) = typeof(x).parameters[i]

needs IPO from v0.7 to infer.

1 Like

You probably thought about this already, but the Julian way would be to dispatch on Example every time you need to use the type parameter T. For example:

julia> findparam(ex::Example{T, N}) where {T, N} = N
findparam (generic function with 1 method)

julia> x = Example(:a, [1, 2, 3])
Example{Symbol,Int64}(:a, [1, 2, 3])

julia> findparam(x)
Int64
16 Likes

This is precisely what I was failing to express! Thanks!

Please don’t suggest the use of this annotation. It’s nearly always wrong, and thus actively unhelpful to mention it, then have to explain that it also causes inference to be fatally wrong. It doesn’t infer, it does the opposite: it tells inference that it’s OK to totally disregard correctness. (piever’s solution is correct).

4 Likes