# How do I put a parametrized struct into another parametrized container?

**URL:** <https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537>\
**Category:** General Usage\
**Tags:** parametric-types\
**Created:** [August 8, 2020, 1:46am UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537 "2020-08-08T01:46:55Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)\
**Post date:** [August 8, 2020, 1:46am UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/1 "2020-08-08T01:46:55Z")

</div>

```julia
using DataStructures
import Base.isless

struct SEvent{F1}
    callback::F1
    time::Float64
end

function SEvent(callback::F1, time) where F1
    SEvent{F1}(callback, time)
end

function isless(a::SEvent, b::SEvent)
    isless(a.time, b.time)
end

```

Now I try to put `SEvent`s into a heap:

```julia
s1 = SEvent(10) do x
    4
end
s2 = SEvent(3) do x
    5
end
a = MutableBinaryMinHeap{Any}() # Or try {SEvent}, the result will be the same

push!(a,s1)

```

This will cause an error:

```julia
ERROR: LoadError: MethodError: Cannot `convert` an object of type 
  DataStructures.MutableBinaryHeapNode{SEvent{var"#9#10"}} to an object of type 
  DataStructures.MutableBinaryHeapNode{Any}

```

Is there no way to put a parametrized struct into a parametrized container like a heap?

---

<div class="post-metadata">

**Author:** ![doomphoenix-qxz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doomphoenix-qxz/32/7009_2.png) [@doomphoenix-qxz](https://discourse.julialang.org/u/doomphoenix-qxz)\
**Post date:** [August 8, 2020, 4:00am UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/2 "2020-08-08T04:00:01Z")

</div>

> [@NightMachinary](#):
>
> `a = MutableBinaryMinHeap{Any}()`

Try replacing this with  
`a = MutableBinaryMinHeap{typeof(s1)}()`

This worked for me. If you’ve ever programmed in C++, you can think of Julia parameterized structs like (much easier to use) C++ template classes. The type of object you try to put into the container must match the type of object it’s expecting!

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 8, 2020, 8:11am UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/3 "2020-08-08T08:11:54Z")

</div>

> [@NightMachinary](#):
>
> ```julia
> a = MutableBinaryMinHeap{Any}() # Or try {SEvent}, the result will be the same
> 
> push!(a,s1)
> 
> ```

why not just something like

```julia
MutableBinaryMinHeap([s1])

```

?

---

<div class="post-metadata">

**Author:** ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)\
**Post date:** [August 8, 2020, 9:57am UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/4 "2020-08-08T09:57:47Z")

</div>

The problem is that I want to put SEvents with different parameters in it. (I.e., SEvents with different callbacks.)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 8, 2020, 11:17am UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/5 "2020-08-08T11:17:51Z")

</div>

In that case, you might as well just use a container with type `Any`.

---

<div class="post-metadata">

**Author:** ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)\
**Post date:** [August 8, 2020, 11:47am UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/6 "2020-08-08T11:47:44Z")

</div>

I did, but it errors:

```julia
ERROR: LoadError: MethodError: Cannot `convert` an object of type 
  DataStructures.MutableBinaryHeapNode{SEvent{var"#9#10"}} to an object of type 
  DataStructures.MutableBinaryHeapNode{Any}

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [August 8, 2020, 3:22pm UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/7 "2020-08-08T15:22:10Z")

</div>

This seems to be a problem with the implementation of `MutableBinaryMinHeap`/`MutableBinaryHeapNode`. It works for other containers.

```julia
julia> a = Vector{Any}()
0-element Array{Any,1}

julia> push!(a, s1)
1-element Array{Any,1}:
 SEvent{getfield(Main, Symbol("##55#56"))}(getfield(Main, Symbol("##55#56"))(), 10.0)

```

---

<div class="post-metadata">

**Author:** ![doomphoenix-qxz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doomphoenix-qxz/32/7009_2.png) [@doomphoenix-qxz](https://discourse.julialang.org/u/doomphoenix-qxz)\
**Post date:** [August 8, 2020, 8:47pm UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/8 "2020-08-08T20:47:14Z")

</div>

Can confirm @tomerarnon’s point. You can push both `s1` and `s2` into a `Vector{Any}`. Perhaps file an issue in DataStructures.jl?

---

<div class="post-metadata">

**Author:** ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)\
**Post date:** [August 8, 2020, 8:55pm UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/9 "2020-08-08T20:55:17Z")

</div>

I filed an [issue](https://github.com/JuliaCollections/DataStructures.jl/issues/648).

---

<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:** [August 8, 2020, 10:03pm UTC](https://discourse.julialang.org/t/how-do-i-put-a-parametrized-struct-into-another-parametrized-container/44537/10 "2020-08-08T22:03:08Z")

</div>

I think the problem happens inside [this method](https://github.com/JuliaCollections/DataStructures.jl/blob/64cc58956c7ca2fb2c0600fb8431c62950250d34/src/heaps/mutable_binary_heap.jl#L205--L214). Specially, this line:

```julia
push!(nodes, MutableBinaryHeapNode(convert(T, v), i))

```

because what happens is basically the same as:

```julia
julia> struct Wrapper{T}; v :: T; end

julia> vec = Vector{Wrapper{Any}}()
0-element Array{Wrapper{Any},1}

julia> push!(vec, Wrapper(convert(Any, 10)))
ERROR: MethodError: Cannot `convert` an object of type 
  Wrapper{Int64} to an object of type 
  Wrapper{Any}
...

```

In other words, the `push!` wraps your value inside a wrapper struct (`MutableBinaryHeapNode` more specifically), the code expects that converting your value to the type of the heap (i.e., `Any` or `SEvents`) they will create a `MutableBinaryHeapNode{Any}` (or `...{SEvents}`) and then push it into a vector. However, `typeof(convert(Any, s_event_obj))` is `typeof(s_event_obj)` not `Any`, and therefore the object created is a `MutableBinaryHeapNode{typeof(s_event_obj)}` and not a `MutableBinaryHeapNode{Any}` and cannot be pushed into a `Vector{MutableBinaryHeapNode{Any}}` because it is the wrong type.

I see two workarounds (i.e., not considering a fix in their side):

1. You need to use a concrete type instead of an abstract type. What would need you to STOP using a type that is different for each function inside it (i.e., not parametrized by closure). You would need to do:

```julia
struct SEvent
    callback::Function # or Any
    time::Float64
end

```

1. (shameless self-promotion) Use my implementation of a `MutableBinaryHeap`, that I prefer to `DataStructures.jl` implementation. It is available in [TrackingHeaps.jl](https://github.com/henriquebecker91/TrackingHeaps.jl) (registered package, you can just `add` it). It is fully documented, and have come up recently [in this thread](https://discourse.julialang.org/t/priority-queue-choice/42783).
