Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia methoderror for eltype style functionality

I have an abstract container AbstractContainer parameterised over a type T which indicates the type of what is in the container. Every subtype (in this case FloatContainer) then specifies what's actually in the container (in this case a Float64).

Ideally I'd have a means of getting back what type is in the container if I only have the container type. This way I could use it in another struct (in this example MultiplyBy)

I was thinking of doing it in a similar way to Julia's internal eltype function but I can't get it to work. I always get a method error (see the last snippet for the detailed error message)

abstract type AbstractContainer{T} end


gettype(::Type{AbstractContainer{T}}) where T = T

struct FloatContainer <: AbstractContainer{Float64}
  x::Float64
end


struct MultiplyBy{T<:AbstractContainer}
  x::gettype(T)
end


function process(m::MultiplyBy, v::AbstractContainer)
  return typeof(v)(m.x*v.x)
end


function main()
  x = FloatContainer(2.0)

  y = FloatContainer(3.0)
  op = MultiplyBy{FloatContainer}(y)

  z = process(op, x)
  println(z.x)
end


main()
ERROR: LoadError: MethodError: no method matching gettype(::TypeVar)
Closest candidates are:
  gettype(!Matched::Type{AbstractContainer{T}}) where T at /Users/.../test.jl:6

I must admit I'm very new to Julia but I'm very interested in learning more about it. So any tips are appreciated - either on how to solve this problem differently or where my mistake is.

like image 683
user42961 Avatar asked Mar 09 '26 07:03

user42961


1 Answers

Determining element type

Your gettype does not work because it dispatches on abstract types, but your container objects will all have concrete types. You have to use the subtype operator in order to dispatch correctly.

Compare dispatch on abstract types:

julia> eltype1(::Type{AbstractContainer{T}}) where T = T
eltype1 (generic function with 1 method)

julia> eltype1(FloatContainer)
ERROR: MethodError: no method matching eltype1(::Type{FloatContainer})
Closest candidates are:
  eltype1(::Type{AbstractContainer{T}}) where T at REPL[4]:1
Stacktrace:
 [1] top-level scope at REPL[5]:1

julia> eltype1(AbstractContainer{Float64})
Float64

with dispatch on subtypes of abstract types:

julia> eltype2(::Type{<:AbstractContainer{T}}) where T = T
eltype2 (generic function with 1 method)

julia> eltype2(FloatContainer)
Float64

julia> eltype2(AbstractContainer{Float64})
Float64

Prefer dispatch variables to explicit eltype calls

Calling eltype directly is usually unnecessary; you can make the parametric type explicit during dispatch.

This solution uses only parametric types:

julia> struct Container{T}
           x::T
       end

julia> struct MultiplyBy{T}
           x::T
       end

julia> MulitplyBy(x::Container{T}) where T = MultiplyBy{T}(x.x)
MulitplyBy (generic function with 1 method)

julia> process(m::MultiplyBy, x::Container{T}) where T = Container{T}(m.x * x.x)
process (generic function with 1 method)

julia> a = Container(2.0)
Container{Float64}(2.0)

julia> b = Container(3.0)
Container{Float64}(3.0)

julia> op = MulitplyBy(b)
MultiplyBy{Float64}(3.0)

julia> process(op, a)
Container{Float64}(6.0)
like image 186
David Varela Avatar answered Mar 12 '26 12:03

David Varela



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!