# Store abstract types in a container

**URL:** <https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764>\
**Category:** Performance\
**Created:** [October 5, 2020, 6:12am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764 "2020-10-05T06:12:30Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![isentropic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/isentropic/32/11894_2.png) [@isentropic](https://discourse.julialang.org/u/isentropic)\
**Post date:** [October 5, 2020, 6:12am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/1 "2020-10-05T06:12:30Z")

</div>

What is the best way to store abstract types in an array let’s say:  
I have array world geometry. Each world component is essentially an object. Each array element could be A or B type, but both A\<:C, B\<:C. So I need a Array{C} to store these objects. In case I do it this way I get compiler type inference warnings.

What is the best way to overcome this limitaion?

Suggestions I already got:

1. Create dummy class D with integer coding that would distinguish the types.
2. It should not cause a lot of trouble with regard to performance, but it does upon testing. Type stability gives around 20% performance which is important.

---

<div class="post-metadata">

**Author:** ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)\
**Post date:** [October 5, 2020, 6:25am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/2 "2020-10-05T06:25:04Z")

</div>

The first thing is to identify if there is actually a performance problem if you just put them in an abstractly typed container… because otherwise that’s what I would suggest too.

---

<div class="post-metadata">

**Author:** ![kernelmethod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kernelmethod/32/35480_2.png) [@kernelmethod](https://discourse.julialang.org/u/kernelmethod)\
**Post date:** [October 5, 2020, 7:21am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/3 "2020-10-05T07:21:44Z")

</div>

Without seeing any code or how your types are defined, it’s a bit hard to say. Perhaps you could create a type `WorldComponentsCollection` defined as

```julia
struct WorldComponentsCollection
    collection_A::Vector{A}
    collection_B::Vector{B}
end

function WorldComponentsCollection(components)
    collection_A = filter(c -> isa(c, A), components)
    collection_B = filter(c -> isa(c, B), components)
    WorldComponentsCollection(collection_A, collection_B)
end

```

Then you could pre-process your array of components by storing them in a `WorldComponentsCollection` instance, and operate on the `WorldComponentsCollection` instead of the array. That would eliminate any type inference issues.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 5, 2020, 8:00am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/4 "2020-10-05T08:00:36Z")

</div>

Note that `Array` by itself is an abstract type - you haven’t defined the dimensions. A full specification would be `Array{C, 1}`, which is a container of one dimension holding objects that are (a subtype) of `C`.

Have you tried `Vector{T} where T <: C` or `Vector{Union{A, B}}`? This avoids the abstract type.

Moreover, what sort of compiler warning do you observe?

---

<div class="post-metadata">

**Author:** ![isentropic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/isentropic/32/11894_2.png) [@isentropic](https://discourse.julialang.org/u/isentropic)\
**Post date:** [October 5, 2020, 8:08am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/5 "2020-10-05T08:08:30Z")

</div>

At this point I do not care of it is 2d or 1d array. I believe union A B is already ambigous and get type inference warnings

---

<div class="post-metadata">

**Author:** ![isentropic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/isentropic/32/11894_2.png) [@isentropic](https://discourse.julialang.org/u/isentropic)\
**Post date:** [October 5, 2020, 8:14am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/6 "2020-10-05T08:14:21Z")

</div>

You have understood my problem very well, and I think your solution is very good. However, the reason why I store these 2 types in a single array is that, there would be a lot of `WorldComponent` changing.

That is, the order of the elements in `collection_C:Vector{Union(A,B)}` is crucial and that is why I want to store it in a contiguous array because in my case it is connected chain (like self connected linked list), and in the simulation I would run over all WorldComponents for many laps. The issue is that cost of simulating one `WorldComponent` is trivial, the real issue comes because of many laps.

I do not mind storing A,B separately, as long as I can note the initial order somehow (I really do not know how at this point, perhaps by integer coding again?) and guarantee good performance when using A, B containers separately (in terms of memory moving and stuff).

Let me know if I explained myself correctly and thanks for your response in advance

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 5, 2020, 10:17am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/7 "2020-10-05T10:17:12Z")

</div>

`Union{A,B}` is going to be faster because small unions are very well optimized.

What type does your actual array have? How do you construct it? What sort of errors or warnings do you get? I assumed, based on you writing `Array{C}`, that you left the dimension unspecified somewhere, which is going to lead to suboptimal performance, regardless of what `C` is precisely.

Moreover, are you certain this part of the code is your bottleneck? Maybe there’s some other part that’s taking up more time, some example code would go a long way to diagnosing the issue.

---

<div class="post-metadata">

**Author:** ![kernelmethod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kernelmethod/32/35480_2.png) [@kernelmethod](https://discourse.julialang.org/u/kernelmethod)\
**Post date:** [October 6, 2020, 5:00am UTC](https://discourse.julialang.org/t/store-abstract-types-in-a-container/47764/8 "2020-10-06T05:00:36Z")

</div>

I suppose you could modify your definition to, perhaps,

```julia
struct WorldComponentsCollection
    collection_A::Vector{Tuple{Int64,A}}
    collection_B::Vector{Tuple{Int64,B}}
end

function WorldComponentsCollection(components)
    components = enumerate(components)
    collection_A = filter(c -> isa(c[2], A), components)
    collection_B = filter(c -> isa(c[2], B), components)
    WorldComponentsCollection(collection_A, collection_B)
end

```

Then `collection_A[i]` would store a 2-tuple whose first element is an index into the original `components` array and whose second element is an component of type `A`, and similar for `collection_B`. Then you could process your elements in order by doing something analogous to the merge step in a merge sort, e.g.

```julia
function process(c::WorldComponentsCollection)
    i = j = 1
    while i <= length(c.collection_A) && j <= length(c.collection_B)
        if c.collection_A[i][1] < c.collection_B[j][1]
            process(c.collection_A[i][2])
            i += 1
        else
            process(c.collection_B[j][2])
            j += 1
        end
    end

    while i <= length(c.collection_A)
        process(c.collection_A[i][2])
        i += 1
    end

    while j <= length(c.collection_B)
        process(c.collection_B[i][2])
        j += 1
    end
end

```
