From a7d6a3df0f043f5df5c8b65433c722c5d61bd6c6 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Fri, 21 Jul 2023 15:58:49 -0400 Subject: [PATCH 1/3] Add more constructors for `LittleDict` and allow other AbstractVector types --- src/little_dict.jl | 31 +++++++++++++++---------------- test/test_little_dict.jl | 1 + 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/little_dict.jl b/src/little_dict.jl index 25e99e6..4a8db1d 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 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}) From 1b63bc8d08b62d0f40f03e7b81b853b78ff4ece6 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Fri, 21 Jul 2023 16:19:37 -0400 Subject: [PATCH 2/3] version bump --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 2a8e933..9a258dd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "OrderedCollections" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.6.0" +version = "1.6.2" [compat] julia = "1.6" From f9df541570a33f4c258f2d5155c114554e9c2703 Mon Sep 17 00:00:00 2001 From: "Zachary P. Christensen" Date: Fri, 21 Jul 2023 16:19:44 -0400 Subject: [PATCH 3/3] fix `empty(::LittleDict)` The old version just called `LittleDict{K, V}()`, but that may not be an accurate empty version of the type passed. This now calls empty on the keys and values seperately. --- src/little_dict.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/little_dict.jl b/src/little_dict.jl index 4a8db1d..8b678a6 100644 --- a/src/little_dict.jl +++ b/src/little_dict.jl @@ -183,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