As a minimum example, one field in my struct can be a complex-valued matrix or vector:
struct foo_1
a::VecOrMat{ComplexF64}
end
VecOrMat{ComplexF64}(x::Vector) = Vector{ComplexF64}(x)
VecOrMat{ComplexF64}(x::Matrix) = Matrix{ComplexF64}(x)
which allows the input to be, e.g. an integer vector, and convert it to complex floating vector:
foo_1([1, 2])
foo_1(Complex{Float64}[1.0 + 0.0im, 2.0 + 0.0im])
This works as expected; however, another field in my struct can be a floating-point number or vector of such:
struct foo_2
x::Union{Float64, Vector{Float64}}
end
Union{Float64, Vector{Float64}}(x::Number) = Float64(x)
Union{Float64, Vector{Float64}}(x::Vector) = Vector{Float64}(x)
This however errors:
foo_2(1)
MethodError: Cannot
convert
an object of type
Int64 to an object of type
Union{Float64, Array{Float64,1}}
Closest candidates are:
convert(::Type{T}, !Matched::T) where T at essentials.jl:171
Union{Float64, Array{Float64,1}}(::Number) at In[3]:5Stacktrace:
[1] foo_2(::Int64) at ./In[3]:2
[2] top-level scope at In[6]:1
given VecOrMat
is just Union{Array{T,1}, Array{T,2}} where T
, why is be behavior of foo_2
different from foo_1
? @code_typed
shows
@code_typed foo_1([1, 2])
CodeInfo(
1 β %1 = Main.foo_1::Core.Compiler.Const(foo_1, false)
β %2 = Core.fieldtype(%1, 1)::Type{Union{Array{Complex{Float64},1}, Array{Complex{Float64},2}}}
β %3 = invoke Base.convert(%2::Type{Union{Array{Complex{Float64},1}, Array{Complex{Float64},2}}}, _2::Array{Int64,1})::Any
β %4 = %new(%1, %3)::foo_1
βββ return %4
) => foo_1
and
@code_typed foo_2([1, 2])
CodeInfo(
1 β %1 = Main.foo_2::Core.Compiler.Const(foo_2, false)
β %2 = Core.fieldtype(%1, 1)::Type{Union{Float64, Array{Float64,1}}}
β Base.convert(%2, x)::Union{}
βββ $(Expr(:unreachable))::Union{}
) => Union{}
I could overload Base.convert()
to make foo_2
work,
import Base.convert
convert(::Type{Union{Float64, Vector{Float64}}}, x::Number) = Float64(x)
convert(::Type{Union{Float64, Vector{Float64}}}, x::Vector) = Vector{Float64}(x)
but still wondering the reason why the error happens, and whatβs a better way to deal with this error? Thanks!