Can I overload []?

Hi,

I’m wondering whether I can overload . I’m wrapping a Dict{type::UUID, Vector{Element}} in another type (MyType) in order to make sure all elements are stored under the correct key via a put(mt::MyType, e::Element) function. I want to get values using mt[type] but for that I would have to overload the ‘operator’. Can I do that? And how?

Thanks,
Stef

Yeah. Just overload getindex and setindex.

6 Likes

Thanks!

Here is one way to see how these type of syntaxes work (and thus also what you need to overload):

julia> Meta.@lower a[i, j]
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope'
1 ─ %1 = Base.getindex(a, i, j)
└──      return %1
))))

julia> Meta.@lower a[i, j] = x
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope'
1 ─     Base.setindex!(a, x, i, j)
└──     return x
))))
9 Likes

Hi,

I’m still running into obstacles. I’m guessing the indices in the code you provided are Int’s? How does it work when I want to override that when I have Blueprint objects as an index?

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

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 put!(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 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:

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:

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