Hi all, just started learning Julia, and I think I’m missing something really obvious here. I’m trying to make a type indexable, but I get an error when using the [ …] syntax. Specifically, if g is an instance of my type, getindex(g,1) works fine, but g[1] gives me an error. The getindex I’ve defined seems like it should be suitably general to match this type, and this is especially weird to me because the documentation says that g[1] should be compiled as getindex(g,1). Example:
struct Graded{S,T}
summands :: Dict{S,T}
end
function getindex(x::Graded{S,T}, k::S) where {S,T}
return x.summands[k]
end
d = Dict{Int,Array{Int}}([0=>[], 1=>[1,2,3], 2=>[10,11,12]])
g = Graded{Int,Array{Int}}(d)
print(getindex(g,1))
print(g[1])
The last line gives the error:
ERROR: LoadError: MethodError: no method matching getindex(::Graded{Int64,Array{Int64,N} where N}, ::Int64)
1 Like
The problem here is that g[1]
always calls Base.getindex
, while your function definition has in fact made a new function in your current module. The solution is to always qualify functions you are trying to extend, when the original definition is in another module:
julia> @which getindex
Main
julia> methods(getindex) # just one:
# 1 method for generic function "getindex":
[1] getindex(x::Graded{S, T}, k::S) where {S, T} in Main at REPL[523]:1
julia> methods(Base.getindex) |> length
517
julia> function Base.getindex(x::Graded{S,T}, k::S) where {S,T}
return x.summands[k]
end
julia> print(g[1])
[1, 2, 3]
It’s a little strange to think that you could mean anything else. But the general rule makes more sense – for instance it lets you use words like sum
or sign
as variable names within a function, so long as you assign to them before reading from them, without worrying that these also exist as functions exported by Base.
7 Likes