diff --git a/Project.toml b/Project.toml index 93573fd..9a258dd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "OrderedCollections" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.6.1" +version = "1.6.2" [compat] julia = "1.6" diff --git a/src/little_dict.jl b/src/little_dict.jl index 25e99e6..8b678a6 100644 --- a/src/little_dict.jl +++ b/src/little_dict.jl @@ -1,4 +1,8 @@ -const StoreType = Union{<:Tuple, <:Vector} +const StoreType{T} = Union{Tuple{Vararg{T}}, AbstractVector{T}} + +@noinline function _throw_unequal_lengths(nk::Int, nv::Int) + throw(ArgumentError("Number of keys ($nk) differs from number of values ($nv).")) +end """ LittleDict(keys, vals)<:AbstractDict @@ -28,22 +32,18 @@ as well as on how many hash collisions occur etc. copies to create the `LittleDict`, so `LittleDict(ks::Tuple, vs::Tuple)` is the fastest constructor of all. """ -struct LittleDict{K,V,KS<:StoreType,VS<:StoreType} <: AbstractDict{K, V} +struct LittleDict{K, V, KS<:StoreType{K}, VS<:StoreType{V}} <: AbstractDict{K, V} keys::KS vals::VS - function LittleDict{K,V,KS,VS}(keys,vals) where {K,V,KS,VS} - if length(keys) != length(vals) - throw(ArgumentError( - "Number of keys ($(length(keys))) differs from " * - "number of values ($(length(vals))" - )) - end - K<:eltype(KS) || ArgumentError("Invalid store type $KS, for key type $K") - V<:eltype(VS) || ArgumentError("Invalid store type $VS, for value type $K") - - return new(keys,vals) + function LittleDict{K, V, KS, VS}(keys, vals) where {K, V, KS, VS} + nk = length(keys) + nv = length(vals) + nk == nv || _throw_unequal_lengths(Int(nk), Int(nv)) + return new{K, V, KS, VS}(keys, vals) end + LittleDict{K, V, <:Tuple, <:Tuple}() where {K, V} = new{K, V, Tuple{}, Tuple{}}((), ()) + LittleDict{K, V, KS, VS}() where {K, V, KS, VS} = LittleDict{K, V, KS, VS}(KS(), VS()) end function LittleDict{K,V}(ks::KS, vs::VS) where {K,V, KS<:StoreType,VS<:StoreType} @@ -54,7 +54,6 @@ function LittleDict(ks::KS, vs::VS) where {KS<:StoreType,VS<:StoreType} return LittleDict{eltype(KS), eltype(VS)}(ks, vs) end - # Other iterators should be copied to a Vector LittleDict(ks, vs) = LittleDict(collect(ks), collect(vs)) @@ -110,8 +109,8 @@ end isordered(::Type{<:LittleDict}) = true # For now these are internal UnionAlls for dispatch purposes -const UnfrozenLittleDict{K,V} = LittleDict{K,V, Vector{K}, Vector{V}} -const FrozenLittleDict{K,V} = LittleDict{K,V, <:Tuple, <:Tuple} +const UnfrozenLittleDict{K, V} = LittleDict{K, V, <:AbstractVector{K}, <:AbstractVector{V}} +const FrozenLittleDict{K, V} = LittleDict{K, V, <:Tuple, <:Tuple} ##### Methods that all AbstractDicts should implement @@ -184,7 +183,9 @@ function merge( end -Base.empty(dd::LittleDict{K,V}) where {K,V} = LittleDict{K,V}() +function Base.empty(dd::LittleDict{K,V}) where {K,V} + LittleDict{K, V}(empty(getfield(dd, :keys)), empty(getfield(dd, :vals))) +end ######## Methods that all mutable AbstractDict's should implement diff --git a/test/test_little_dict.jl b/test/test_little_dict.jl index d6edd99..c4622a8 100644 --- a/test/test_little_dict.jl +++ b/test/test_little_dict.jl @@ -39,6 +39,7 @@ using OrderedCollections: FrozenLittleDict, UnfrozenLittleDict end @testset "Constructors" begin + @test isa(@inferred(LittleDict{Any, Any, <:Tuple, <:Tuple}()), LittleDict{Any, Any, Tuple{}, Tuple{}}) @test isa(@inferred(LittleDict()), LittleDict{Any,Any}) @test isa(@inferred(LittleDict([(1,2.0)])), LittleDict{Int,Float64})