Mercurial > repos > public > sbplib_julia
changeset 749:688767a6f3eb
Merge feature/static_dict
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Fri, 19 Mar 2021 16:40:30 +0100 |
parents | 6dd9f97fc2be (current diff) 9807799592d4 (diff) |
children | f88b2117dc69 0159a91fc55a |
files | |
diffstat | 3 files changed, 151 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Sbplib.jl Wed Mar 17 22:21:01 2021 +0100 +++ b/src/Sbplib.jl Fri Mar 19 16:40:30 2021 +0100 @@ -1,5 +1,6 @@ module Sbplib +include("StaticDicts/StaticDicts.jl") include("RegionIndices/RegionIndices.jl") include("LazyTensors/LazyTensors.jl") include("Grids/Grids.jl")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/StaticDicts/StaticDicts.jl Fri Mar 19 16:40:30 2021 +0100 @@ -0,0 +1,82 @@ +module StaticDicts + +export StaticDict + +""" + StaticDict{K,V,N} <: AbstractDict{K,V} + +A static dictionary implementing the interface for an `AbstractDict`. A +`StaticDict` is fully immutable and after creation no changes can be made. + +The immutable nature means that `StaticDict` can be compared with `===`, in +constrast to regular `Dict` or `ImmutableDict` which can not. (See +https://github.com/JuliaLang/julia/issues/4648 for details) One important +aspect of this is that `StaticDict` can be used in a struct while still +allowing the struct to be comared using the default implementation of `==` for +structs. + +Lookups are done by linear search. + +Duplicate keys are not allowed and an error will be thrown if they are passed +to the constructor. +""" +struct StaticDict{K,V,N} <: AbstractDict{K,V} + pairs::NTuple{N,Pair{K,V}} + + function StaticDict{K,V}(pairs::Vararg{Pair,N}) where {K,V,N} + if !allunique(first.(pairs)) + throw(DomainError(pairs, "keys must be unique")) + end + return new{K,V,N}(pairs) + end +end + +function StaticDict(pairs::Vararg{Pair}) + K = typejoin(firsttype.(pairs)...) + V = typejoin(secondtype.(pairs)...) + return StaticDict{K,V}(pairs...) +end + +StaticDict(pairs::NTuple{N,Pair} where N) = StaticDict(pairs...) + +function Base.get(d::StaticDict, key, default) + for p ∈ d.pairs + if key == p.first + return p.second + end + end + + return default +end + +Base.iterate(d::StaticDict) = iterate(d.pairs) +Base.iterate(d::StaticDict, state) = iterate(d.pairs,state) +Base.length(d::StaticDict) = length(d.pairs) + + +""" + merge(d1::StaticDict, d2::StaticDict) + +Merge two `StaticDict`. Repeating keys is considered and error. This may +change in a future version. +""" +function Base.merge(d1::StaticDict, d2::StaticDict) + return StaticDict(d1.pairs..., d2.pairs...) +end + + +""" + firsttype(::Pair{T1,T2}) + +The type of the first element in the pair. +""" +firsttype(::Pair{T1,T2}) where {T1,T2} = T1 + +""" + secondtype(::Pair{T1,T2}) + +The type of the secondtype element in the pair. +""" +secondtype(::Pair{T1,T2}) where {T1,T2} = T2 + +end # module
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/StaticDicts/StaticDicts_test.jl Fri Mar 19 16:40:30 2021 +0100 @@ -0,0 +1,68 @@ +using Test +using Sbplib.StaticDicts + +@testset "StaticDicts" begin + +@testset "StaticDict" begin + @testset "constructor" begin + @test (StaticDict{Int,Int,N} where N) <: AbstractDict + + d = StaticDict(1=>2, 3=>4) + @test d isa StaticDict{Int,Int} + @test d[1] == 2 + @test d[3] == 4 + + @test StaticDict((1=>2, 3=>4)) == d + + @test StaticDict() isa StaticDict + @test StaticDict{Int,String}() isa StaticDict{Int,String,0} + + @test StaticDict(1=>3, 2=>4.) isa StaticDict{Int,Real} + @test StaticDict(1. =>3, 2=>4) isa StaticDict{Real,Int} + @test StaticDict(1. =>3, 2=>4.) isa StaticDict{Real,Real} + + @test_throws DomainError StaticDict(1=>3, 1=>3) + end + + @testset "length" begin + @test length(StaticDict()) == 0 + @test length(StaticDict(1=>1)) == 1 + @test length(StaticDict(1=>1, 2=>2)) == 2 + end + + @testset "equality" begin + @test StaticDict(1=>1) == StaticDict(1=>1) + @test StaticDict(2=>1) != StaticDict(1=>1) + @test StaticDict(1=>2) != StaticDict(1=>1) + + @test StaticDict(1=>1) === StaticDict(1=>1) #not true for a regular Dict + @test StaticDict(2=>1) !== StaticDict(1=>1) + @test StaticDict(1=>2) !== StaticDict(1=>1) + end + + @testset "get" begin + d = StaticDict(1=>2, 3=>4) + + @test get(d,1,6) == 2 + @test get(d,3,6) == 4 + @test get(d,5,6) == 6 + end + + @testset "iterate" begin + pairs = [1=>2, 3=>4, 5=>6] + + d = StaticDict(pairs...) + @test collect(d) == pairs + end + + @testset "merge" begin + @test merge( + StaticDict(1=>3, 2=> 4), + StaticDict(3=>5,4=>6)) == StaticDict( + 1=>3, 2=>4, 3=>5, 4=>6 + ) + @test_throws DomainError merge(StaticDict(1=>3),StaticDict(1=>3)) + end +end + +end