# Problems overloading setindex!()

**URL:** <https://discourse.julialang.org/t/problems-overloading-setindex/50852>\
**Category:** New to Julia\
**Created:** [November 27, 2020, 9:36am UTC](https://discourse.julialang.org/t/problems-overloading-setindex/50852 "2020-11-27T09:36:40Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![stefkuypers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefkuypers/32/19185_2.png) [@stefkuypers](https://discourse.julialang.org/u/stefkuypers)\
**Post date:** [November 27, 2020, 9:36am UTC](https://discourse.julialang.org/t/problems-overloading-setindex/50852/1 "2020-11-27T09:36:40Z")

</div>

Hi,

I’m running into obstacles trying to overload setindex!() for a dict wrapper type. I’m probably missing something obvious here but I can’t figure out what exactly.

I’m getting an error when adding a Consumable which is an implementation of the abstract type Entity.

```julia
abstract type Entity end

struct Entities
    entities::Dict{Blueprint,Vector{Entity}}
    Entities() = new(Dict{Blueprint,Vector{Entity}}())
end

Base.keys(entities::Entities) = keys(entities.entities)
Base.values(entities::Entities) = values(entities.entities)
Base.getindex(entities::Entities, index::Blueprint) = entities.entities[index]
Base.setindex!(entities::Entities, e::Array{Entity,1}, index::Blueprint) = (entities.entities[index] = e[1])
Base.setindex!(entities::Entities, e::Entity, index::Blueprint) = (entities.entities[index] = e)

function Base.push!(entities::Entities, entity::Entity)
    if entity.blueprint in keys(entities)
        push!(entities[entity.blueprint], entity)
    else
        entities[entity.blueprint] = Vector{Entity}([entity])
    end

    return entities
end

function Base.pop!(entities::Entities, blueprint::Blueprint)
    if blueprint in keys(entities)
        return pop!(entities[blueprint])
    else
        return nothing
    end
end

struct Consumable <: Entity
    id::UUID
    blueprint::Blueprint
    lifecycle::SingleUse
    Consumable(blueprint) = new(uuid4(), blueprint, SingleUse())
end

```

I tried leaving out one of the implementations of setindex!() but in both cases I get an error. If I leave out the first implementation I get:

```julia
ERROR: MethodError: no method matching setindex!(::Entities, ::Array{Entity,1}, ::ConsumableBlueprint)
Closest candidates are:
  setindex!(::Entities, ::Entity, ::Blueprint) at /Users/stef/Programming/Julia Projects/loreco-abm/cockpit/production/entities.jl:80
Stacktrace:
 [1] put!(::Entities, ::Consumable) at /Users/stef/Programming/Julia Projects/loreco-abm/cockpit/production/entities.jl:86
 [2] top-level scope at none:1

```

And if I add that implementation I get:

```julia
ERROR: MethodError: Cannot `convert` an object of type Consumable to an object of type Array{Entity,1}
Closest candidates are:
  convert(::Type{T}, ::AbstractArray) where T<:Array at array.jl:554
  convert(::Type{T}, ::T) where T<:AbstractArray at abstractarray.jl:14
  convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.5/LinearAlgebra/src/factorization.jl:55
  ...
Stacktrace:
 [1] setindex!(::Dict{Blueprint,Array{Entity,1}}, ::Consumable, ::ConsumableBlueprint) at ./dict.jl:380
 [2] setindex!(::Entities, ::Array{Entity,1}, ::ConsumableBlueprint) at /Users/stef/Programming/Julia Projects/loreco-abm/cockpit/production/entities.jl:79
 [3] put!(::Entities, ::Consumable) at /Users/stef/Programming/Julia Projects/loreco-abm/cockpit/production/entities.jl:86
 [4] top-level scope at none:1

```

Thanks in advance,  
Stef

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [November 27, 2020, 11:07am UTC](https://discourse.julialang.org/t/problems-overloading-setindex/50852/2 "2020-11-27T11:07:18Z")

</div>

```julia
Base.setindex!(entities::Entities, e::Array{Entity,1}, index::Blueprint) = (entities.entities[index] = e[1])

```

I find this a bit weird, as you dispatch on `Array{Entity,1}` just to only extract the first element. What happens if there are two elements in the vector? Why do you need this method in the first place if you only expect one element? Then at least I would do `entities.entities[index] = only(e)` so it errors if that assumption is violated.

The error comes from the fact that your `entities` dict stores objects of type `Vector{Entity}`, but you specifically instruct to extract the element from the `Vector{Entity}` that you have, which means you pass the wrong type. The other setindex! method also passes an Entity, and not a Vector of them.

I have no idea what the code is supposed to do, but maybe your issue goes away if you do:

```julia
Base.setindex!(entities::Entities, e::Array{Entity,1}, index::Blueprint) = (entities.entities[index] = e) # pass a vector
Base.setindex!(entities::Entities, e::Entity, index::Blueprint) = (entities.entities[index] = [e]) # pass a vector

```

---

<div class="post-metadata">

**Author:** ![stefkuypers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefkuypers/32/19185_2.png) [@stefkuypers](https://discourse.julialang.org/u/stefkuypers)\
**Post date:** [November 27, 2020, 11:15am UTC](https://discourse.julialang.org/t/problems-overloading-setindex/50852/3 "2020-11-27T11:15:49Z")

</div>

Thanks! That solved it! And now I can see what I was overlooking. I only need 1 setindex!() now to make it work: the first one you wrote.
