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.

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
))))

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