Why this behavior?
julia> convert(AbstractFloat, 1)
1.0
julia> convert(Vector{T} where T, [1, 2])
2-element Vector{Int64}:
1
2
ulia> convert(Vector{AbstractFloat}, [1, 2])
2-element Vector{AbstractFloat}:
1.0
2.0
julia> convert(Vector{T} where T <: AbstractFloat, [1, 2])
ERROR: MethodError: no method matching (Vector{A} where A<:AbstractFloat)(::Vector{Int64})
The second of your examples is just converting to Vector.
Note as well that Vector{AbstractFloat}
is completely different from Vector{T} where T <: AbstractFloat
Right, (Vector{T} where T) === Vector
I know the two types are different :
julia> [1.0, 2.0] isa Vector{AbstractFloat}
false
julia> [1.0, 2.0] isa (Vector{T} where T <: AbstractFloat)
true
julia> AbstractFloat[1.0, 2.0] isa Vector{AbstractFloat}
true
julia> AbstractFloat[1.0, 2.0] isa (Vector{T} where T <: AbstractFloat)
true
but I am wondering why convert
is not defined differently .
(so that the fourth of my examples does what I expect)
It basically just comes down to the fact that unionalls are hard to deal with
e.g.
julia> convert(Complex{AbstractFloat}, 1+im)
1.0 + 1.0im
julia> convert(Complex{T} where T <: AbstractFloat, 1+im)
ERROR: MethodError: no method matching (Complex{T} where T<:AbstractFloat)(::Complex{Int64})
Closest candidates are:
(::Type{T})(::T) where T<:Number at boot.jl:760
(::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number} at char.jl:50
(::Type{T})(::Base.TwicePrecision) where T<:Number at twiceprecision.jl:243
Stacktrace:
[1] convert(#unused#::Type{Complex{T} where T<:AbstractFloat}, x::Complex{Int64})
@ Base ./number.jl:7
[2] top-level scope
@ REPL[2]:1
So, you don't think it would be inconsistent or wrong if those UnionAll
MethodError
instead worked?
So long as convert(T, x) isa T
I don't see any problem with it working. It seems to just be that someone defined some convenient methods, but decided that a fully general system here was too hard to do
but I have no idea
The situation that I am in is the following
I have an AbstractSet{CartesianIndex}
that is backed by an Array{Bool}
. Roughly in(elt, set) = set.array[elt]
I also have defined a convert
method from any AbstractSet
to MySet
. But if I convert a MySet
to a MySet
, then I just want to use the same underlying array. So I defined a convert
method. but this convert
method does not handle UnionAll
s correctly. Because, as you said, that's hard.
I think I can fix my situation by replacing the definition
Base.convert(::Type{T}, s::Foo) where {T <: Foo} = T(s.x)
with
Base.convert(::Type{T}, s::Foo) where {T <: Foo} = s ia T ? s : T(s.x)
like https://github.com/JuliaLang/julia/blob/2fbeef8d712ff9151370fd27a3ae07ea8b2e740d/base/array.jl#L614
Last updated: Dec 28 2024 at 04:38 UTC