How to Convert Vector{AbstractType} to Vector{ConcreteType} ?
e.g. Vector{Real} to Vector{Int}
and generate an error if the array contains different concrete types?
e.g. my below example:
I can only think of one way: First convert to Tuple, then collect back to Vector:
but this is really dirty, no?
abstract type Operate end
struct Cut <: Operate
member::String
end
Cut() = Cut("t")
struct Push <: Operate
member::Int
end
Push() = Push(1)
struct Roll <: Operate
member::Symbol
end
Roll() = Roll(:a)
aa = Vector{Operate}(undef, 4)
aa[1] = Roll()
aa[2] = Roll()
aa[3] = Roll()
aa[4] = Roll()
bb = collect(Tuple(aa))
julia> abstract type Operate end
julia> struct Cut <: Operate
member::String
end
julia> Cut() = Cut("t")
Cut
julia> struct Push <: Operate
member::Int
end
julia> Push() = Push(1)
Push
julia> struct Roll <: Operate
member::Symbol
end
julia> Roll() = Roll(:a)
Roll
julia> aa = Vector{Operate}(undef, 4)
4-element Array{Operate,1}:
#undef
#undef
#undef
#undef
julia> aa[1] = Roll()
Roll(:a)
julia> aa[2] = Roll()
Roll(:a)
julia> aa[3] = Roll()
Roll(:a)
julia> aa[4] = Roll()
Roll(:a)
julia> [a for a ∈ aa]
4-element Array{Roll,1}:
Roll(:a)
Roll(:a)
Roll(:a)
Roll(:a)
If you want to throw an error if they aren’t all of one concrete type, a simple approach is
julia> function make_concrete(v)
typeof(first(v))[vᵢ for vᵢ ∈ v]
end
make_concrete (generic function with 1 method)
julia> make_concrete(aa)
4-element Array{Roll,1}:
Roll(:a)
Roll(:a)
Roll(:a)
Roll(:a)
julia> aa[3] = Cut()
Cut("t")
julia> make_concrete(aa)
ERROR: MethodError: Cannot `convert` an object of type Cut to an object of type Roll
Closest candidates are:
convert(::Type{T}, ::T) where T at essentials.jl:170
Roll(::Any) at REPL[6]:2
Stacktrace:
[1] setindex!(::Array{Roll,1}, ::Cut, ::Int64)
[2] make_concrete(::Array{Operate,1})
[3] top-level scope at REPL[17]:1
Note that this wont error if you do define a convert method. If you want it to error anyway, I’d use a loop.