# List of elements with unknown type, is it bad?

**URL:** <https://discourse.julialang.org/t/list-of-elements-with-unknown-type-is-it-bad/53893>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [January 25, 2021, 9:44am UTC](https://discourse.julialang.org/t/list-of-elements-with-unknown-type-is-it-bad/53893 "2021-01-25T09:44:18Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [January 25, 2021, 9:44am UTC](https://discourse.julialang.org/t/list-of-elements-with-unknown-type-is-it-bad/53893/1 "2021-01-25T09:44:18Z")

</div>

Hi,

I have a project where I need to append to a result list, several objects depending on conditions. A MWE is presented in the following code. In practice, I have more subtypes of `ABS` (like ~10). I would like `foo` to be the most efficient (fastest).

To me, the type of `res` is not known and so `foo` is not efficient. I tend to think that a different structure is needed to handle this situation. However, I noticed:

> Surprisingly to me, using `@code_warntype` does not reveal type unstability.

Hence:

- is it the best way to handle this situation?
- should I enforce `res = Vector{Union{A{T},B{T},C{T}}(undef, 0)`? (and later with 10s of subtypes?)
- should I leave it like that?

Thank you for your help,

```julia
using Revise

abstract type ABS end
struct A{T} <: ABS ;a::T;end
struct B{T} <: ABS ;b::T;end
struct C{T} <: ABS ;b::T;end

function foo(x::T) where T
	res = Vector(undef, 0)
	push!(res, A(x))
	push!(res, B(x))
	for i=1:13
		r = rand(T)
		if r < 0.25
			push!(res, A(r))
		elseif r<0.75
			push!(res, B(r))
		else
			push!(res, C(r))
		end
	end
	res
end
	foo(1.2)

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [January 25, 2021, 12:55pm UTC](https://discourse.julialang.org/t/list-of-elements-with-unknown-type-is-it-bad/53893/2 "2021-01-25T12:55:20Z")

</div>

> [@rveltz](#):
>
> Surprisingly to me, using `@code_warntype` does not reveal type unstability.

If I understand correctly you did something like `@code_warntype foo(1.2)`, right? Well, this by itself is not type-unstable. The returned value is always a `Vector{Any}` (that is a concrete type), so the “_function itself_” is type-stable. What is type-unstable is dealing with values obtained _from_ the `Vector`:

```julia
julia> a = foo(1.2);
julia> @code_warntype a[rand(1:15)]
Variables
  #self#::Core.Compiler.Const(getindex, false)
  A::Array{Any,1}
  i1::Int64

Body::Any
1 ─ %1 = Base.arrayref($(Expr(:boundscheck)), A, i1)::Any
└── return %1

```

Because then, the type returned is `Any` (not `Vector{Any}`) and `Any` is the root abstract type, so this can be anything.

If you really need a dynamic number of elements of distinct type, there is not much else to do. If every element is a subtype of `ABS` then I would suggest changing the function first line to `res = Vector{ABS}(undef, 0)` to at least restrict the type a little. Accessing elements will be type unstable anyway (because `ABS` is an abstract type) but maybe the compiler can optimize one or other thing.

I suggest you look at [this recent answer of mine](https://discourse.julialang.org/t/type-stability-problem-vcat-tuple-and-function/53862/5) about how to limit the damage cause by type-instability.

---

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [January 25, 2021, 1:06pm UTC](https://discourse.julialang.org/t/list-of-elements-with-unknown-type-is-it-bad/53893/3 "2021-01-25T13:06:23Z")

</div>

> that is a concrete type

I add forgotten that. For me, `Any` is (was) bad.

> I suggest you look at [this recent answer of mine](https://discourse.julialang.org/t/type-stability-problem-vcat-tuple-and-function/53862/5) about how to limit the damage cause by type-instability.

Thanks

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 25, 2021, 1:14pm UTC](https://discourse.julialang.org/t/list-of-elements-with-unknown-type-is-it-bad/53893/4 "2021-01-25T13:14:42Z")

</div>

Where you will have performance problems is if later you want evaluate functions which take those elements of the array as parameters, and the functions will have to be dynamically dispatched at run time for every element of the array. The best alternative is to try to reorganize the data to avoid mixed-type arrays, but detailed discussions on that can be found in these threads:

> [@Disabling allocations](https://discourse.julialang.org/t/disabling-allocations/51028):
>
> Is there a way of disabling allocations altogether within the body of a function? I optimized my code to avoid all allocations, but they keep creeping back in with changes and are annoying to locate. I would much rather have a compile-time error.

> [@Performance drawback with subtyping](https://discourse.julialang.org/t/performance-drawback-with-subtyping/51939/14):
>
> I agree with you @lmiq, we should study a more realistic case. So I apply the sin function as you did and changed n = 100,000,000. Because with a little n there is a big influencial of processes at operation system. My results was: with dynamic dispatch: 1.120 s (0 allocations: 0 bytes) with splitting: 1.121 s (0 allocations: 0 bytes) with functors: 1.144 s (0 allocations: 0 bytes) with cast: 1.159 s (0 allocations: 0 bytes) simple sum of an array of Float64 of same size: 504.909 ms…

> [@Macro to write function with many conditionals](https://discourse.julialang.org/t/macro-to-write-function-with-many-conditionals/51616/8):
>
> It is even more simple then that. If all types are subtypes of some abstract class, then you can use subtypes function to generate list of all subtypes. It’s little more involved in case of parametric case, so I am not sure whether it is possible to write generic macro that can solve them all, but if you know you hierarchy beforehand you bend it appropriately. As an example for non parametric types, here is an adaptation of the ManualDispatch.jl function function \_unionsplit(type, x, call) …

(look particularly at Skoffer’s answers and the macro he provides in the third thread).
