andyferris / Dictionaries.jl

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

`merge` with `undef` #86

Open mtfishman opened 2 years ago

mtfishman commented 2 years ago

Here is another undef issue I came across:

julia> using Dictionaries

julia> dict = Dictionary{Int, String}([1, 2], undef)
2-element Dictionary{Int64, String}
 1 │ #undef
 2 │ #undef

julia> merge(dict, dict)
ERROR: UndefRefError: access to undefined reference
Stacktrace:
  [1] getindex
    @ ./array.jl:861 [inlined]
  [2] gettokenvalue
    @ ~/.julia/dev/Dictionaries/src/Dictionary.jl:308 [inlined]
  [3] iterate
    @ ~/.julia/dev/Dictionaries/src/AbstractDictionary.jl:54 [inlined]
  [4] _zip_iterate_some
    @ ./iterators.jl:358 [inlined]
  [5] _zip_iterate_some
    @ ./iterators.jl:360 [inlined]
  [6] _zip_iterate_all
    @ ./iterators.jl:350 [inlined]
  [7] iterate
    @ ./iterators.jl:340 [inlined]
  [8] map!(f::typeof(identity), out::Dictionary{Int64, String}, d::Dictionary{Int64, String})
    @ Dictionaries ~/.julia/dev/Dictionaries/src/map.jl:63
  [9] copyto!
    @ ~/.julia/dev/Dictionaries/src/AbstractDictionary.jl:493 [inlined]
 [10] merge(d1::Dictionary{Int64, String}, d2::Dictionary{Int64, String})
    @ Dictionaries ~/.julia/dev/Dictionaries/src/AbstractDictionary.jl:367
 [11] top-level scope
    @ REPL[3]:1

This may point to a need for fixing copyto! with undef, which would fix this and the issue with copy fixed in #85.

andyferris commented 2 years ago

So the closest thing in Base that handles undefined values is probably vcat:

julia> vcat(Vector{String}(undef, 3), ["a", "b", "c"])
6-element Vector{String}:
 #undef
 #undef
 #undef
    "a"
    "b"
    "c"

julia> vcat(["a", "b", "c"], Vector{String}(undef, 3))
6-element Vector{String}:
    "a"
    "b"
    "c"
 #undef
 #undef
 #undef

julia> vcat(Vector{String}(undef, 3), [1, 2, 3])
ERROR: UndefRefError: access to undefined reference
Stacktrace:
 [1] getindex
   @ ./array.jl:861 [inlined]
 [2] setindex!
   @ ./array.jl:916 [inlined]
 [3] _typed_vcat!(a::Vector{Any}, V::Tuple{Vector{String}, Vector{Int64}})
   @ Base ./abstractarray.jl:1551
 [4] _typed_vcat
   @ ./abstractarray.jl:1543 [inlined]
 [5] typed_vcat
   @ ./abstractarray.jl:1619 [inlined]
 [6] vcat(::Vector{String}, ::Vector{Int64})
   @ SparseArrays ~/julia-1.7.2/share/julia/stdlib/v1.7/SparseArrays/src/sparsevector.jl:1123
 [7] top-level scope
   @ REPL[8]:1

julia> vcat([1, 2, 3], Vector{String}(undef, 3))
ERROR: UndefRefError: access to undefined reference
Stacktrace:
 [1] getindex
   @ ./array.jl:861 [inlined]
 [2] setindex!
   @ ./array.jl:916 [inlined]
 [3] _typed_vcat!(a::Vector{Any}, V::Tuple{Vector{Int64}, Vector{String}})
   @ Base ./abstractarray.jl:1551
 [4] _typed_vcat
   @ ./abstractarray.jl:1543 [inlined]
 [5] typed_vcat
   @ ./abstractarray.jl:1619 [inlined]
 [6] vcat(::Vector{Int64}, ::Vector{String})
   @ SparseArrays ~/julia-1.7.2/share/julia/stdlib/v1.7/SparseArrays/src/sparsevector.jl:1123
 [7] top-level scope
   @ REPL[9]:1

We are going to need something like istokenassigned guards around things in both copyto! and merge!. (We cannot support mergewith! in this case).