andyferris / Dictionaries.jl

An alternative interface for dictionaries in Julia, for improved productivity and performance
Other
278 stars 28 forks source link

Dictionary loses type information when indexing by `Indices` with abstract element type #97

Open mtfishman opened 2 years ago

mtfishman commented 2 years ago

For example:

julia> using Dictionaries

julia> d = Dictionary{Tuple,Int}([(1, 1), (1, 2)], [1, 2])
2-element Dictionary{Tuple, Int64}
 (1, 1) │ 1
 (1, 2) │ 2

julia> getindices(d, Indices{Tuple}([(1, 1), (1, 2)]))
2-element Dictionary{Tuple, Any}
 (1, 1) │ 1
 (1, 2) │ 2
andyferris commented 2 years ago

Yes. This is partly the semantics of getindices where all the information about the output keys comes from the indexer's keys (and the output values come from the indexee's values). In the case of d3 = getindices(d1, d2) I would expect d3 to be similar to d2, by which I mean that keys(d3) === keys(d2). Breaking this relationship or narrowing the keytype might have surprising implications - if for example someone wanted to mutate d3 they need to consider not only the keytype of d2 but also the keytype (or possibly even the actual values?) of d1 also.

I'm not sure we might do to improve the situation?

mtfishman commented 2 years ago

Thanks for the response.

I think I see what you are saying, but my issue with the code example above wasn't with the keytype, but instead my concern was that the eltype of the Dictionary gets lost (expanded to Any).

Maybe this example is clearer:

julia> d = Dictionary{Any}(["X", "Y"], [1, 2])
2-element Dictionary{Any, Int64}
 "X" │ 1
 "Y" │ 2

julia> getindices(d, Indices(["X"]))
1-element Dictionary{String, Int64}
 "X" │ 1

julia> getindices(d, Indices{Any}(["X"]))
1-element Dictionary{Any, Any}
 "X" │ 1

I would hope the final one would output:

julia> getindices(d, Indices{Any}(["X"]))
1-element Dictionary{Any, Int64}
 "X" │ 1

I'm ok that the keytype is Any, I think that behavior makes sense.

For some reason it all works fine if the original Dictionary has a concrete keytype:

julia> d = Dictionary(["X", "Y"], [1, 2])
2-element Dictionary{String, Int64}
 "X" │ 1
 "Y" │ 2

julia> getindices(d, Indices(["X"]))
1-element Dictionary{String, Int64}
 "X" │ 1

julia> getindices(d, Indices{Any}(["X"]))
1-element Dictionary{Any, Int64}
 "X" │ 1
andyferris commented 2 years ago

Okay - thanks for clarifying! Yes this does seem like some kind of bug that we should fix.