If I have the following struct:```mutable struct FactorF{V, C, T} # variables, card

If I have the following struct:

mutable struct FactorF{V,C,T} # variables, cardinality, array type
  vals::T
end

and I have an instance of Factor where T happens to be Array{Float64,3}, what is the proper way to access the Float64 ? Here is an example of an approach I found:

import Base: eltype
eltype(::FactorF{V,C,T}) where {V,C,T} = T.parameters[1]

A = FactorF{(1,2,3), (3,3,3), Array{Float64,3}}(rand(3,3,3))
eltype(A) |> println # prints Float64

Is this the proper way to do this?

Note that the original poster on Slack cannot see your response here on Discourse. Consider transcribing the appropriate answer back to Slack, or pinging the poster here on Discourse so they can follow this thread.
(Original message :slack:) (More Info)

1 Like

I’d like

eltype(f::FactorF) = eltype(f.vals)
3 Likes

Thanks @liuyxpp. The definition you propose depends on information stored in a field rather than in the type itself. So I presume that the performance won’t be as good.

@abraunst proposed this other definition in slack:

eltype(::FactorF{V,C,<:AbstractArray{T}}) where {V,C,T} = T

which only depends on info stored in the type. I think I’m gonna go with this one.

I am not sure the performance. But it is not as flexible as eltype(field) approach as the eltype is achieved in a recursive way. Thus if T in your definition is another AbstractArray, then the approach proposed above will only return this AbstractArray type rather than its element type.

Not necessarily. The compiler often propagates constants in such cases, so it won’t even use the value itself.
Also, eltype can be called on type itself, so you can define

eltype(::FactorF{V,C,T}) where {V,C,T} = eltype(T)

T.parameters[1] is certainly not a good choice, because e.g for static arrays the first parameter is size, not the element type.

1 Like

Thanks for the insight!

This doesn’t seem to be true

julia> x=[[1 2; 3 4] for i=1:2, j=1:2]
2×2 Matrix{Matrix{Int64}}:
 [1 2; 3 4]  [1 2; 3 4]
 [1 2; 3 4]  [1 2; 3 4]
julia> eltype(x)
Matrix{Int64} (alias for Array{Int64, 2})
1 Like

Nice catch! It seems to depend on the implementation of eltype of the next level type.