Skip to content

Commit d7643b4

Browse files
committed
ready Accumulator for v1.0
1 parent 577774d commit d7643b4

File tree

2 files changed

+68
-51
lines changed

2 files changed

+68
-51
lines changed

src/accumulator.jl

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ function counter(seq)
3333
end
3434

3535
eltype_for_accumulator(seq::T) where T = eltype(T)
36-
function eltype_for_accumulator(seq::Base.Generator)
37-
Base.@default_eltype(seq)
38-
end
36+
eltype_for_accumulator(seq::Base.Generator) = Base.@default_eltype(seq)
37+
3938

4039

4140
Base.copy(ct::Accumulator) = Accumulator(copy(ct.map))
@@ -44,9 +43,9 @@ Base.length(a::Accumulator) = length(a.map)
4443

4544
## retrieval
4645

47-
Base.get(ct::Accumulator, x, default) = get(ct.map, x, default)
4846
# need to allow user specified default in order to
4947
# correctly implement "informal" AbstractDict interface
48+
Base.get(ct::Accumulator, x, default) = get(ct.map, x, default)
5049

5150
Base.getindex(ct::Accumulator{T,V}, x) where {T,V} = get(ct.map, x, zero(V))
5251

@@ -76,12 +75,11 @@ inc!(ct::Accumulator, x, v::Number) = (ct[x] += v)
7675
inc!(ct::Accumulator{T, V}, x) where {T, V} = inc!(ct, x, one(V))
7776

7877
# inc! is preferred over push!, but we need to provide push! for the Bag interpreation
79-
# which is used by classified_collections.jl
8078
Base.push!(ct::Accumulator, x) = inc!(ct, x)
8179
Base.push!(ct::Accumulator, x, a::Number) = inc!(ct, x, a)
8280

8381
# To remove ambiguities related to Accumulator now being a subtype of AbstractDict
84-
Base.push!(ct::Accumulator, x::Pair) = inc!(ct, x)
82+
Base.push!(ct::Accumulator{P}, x::P) where P<:Pair = inc!(ct, x)
8583

8684

8785
"""
@@ -92,7 +90,9 @@ Decrements the count for `x` by `v` (defaulting to one)
9290
dec!(ct::Accumulator, x, v::Number) = (ct[x] -= v)
9391
dec!(ct::Accumulator{T,V}, x) where {T,V} = dec!(ct, x, one(V))
9492

95-
#TODO: once we are done deprecating `pop!` for `reset!` then add `pop!` as an alias for `dec!`
93+
Base.pop!(ct::Accumulator, x) = dec!(ct, x)
94+
Base.pop!(ct::Accumulator, x, default) = haskey(ct, x) ? dec!(ct, x) : default
95+
9696

9797
"""
9898
merge!(ct1::Accumulator, others...)
@@ -183,6 +183,11 @@ nsmallest(acc::Accumulator, n) = partialsort!(collect(acc), 1:n, by=last, rev=fa
183183
###########################################################
184184
## Multiset operations
185185

186+
"""
187+
MultiplicityException{K,V} <: Exception
188+
189+
For errors related to havign a negetive count when using an Accumulator as a multiset.
190+
"""
186191
struct MultiplicityException{K, V} <: Exception
187192
k::K
188193
v::V

test/test_accumulator.jl

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,53 +2,72 @@
22

33
@testset "Accumulators" begin
44

5-
ct = counter(String)
5+
@testset "Running tests" begin
6+
#TODO: all these tests should be made independent.
7+
# Currently they all need to run in a particular order as they share `ct`
8+
ct = counter(String)
69

7-
@testset "Core Functionality" begin
8-
@assert isa(ct, Accumulator{String,Int})
10+
@testset "Core Functionality" begin
11+
@assert isa(ct, Accumulator{String,Int})
912

10-
@test ct["abc"] == 0
11-
@test !haskey(ct, "abc")
12-
@test isempty(collect(keys(ct)))
13-
end
13+
@test ct["abc"] == 0
14+
@test !haskey(ct, "abc")
15+
@test isempty(collect(keys(ct)))
16+
end
1417

15-
@testset "Test setindex!" begin
16-
ct["b"] = 2
17-
@test ct["b"] == 2
18-
ct["b"] = 0
19-
@test ct["b"] == 0
20-
end
18+
@testset "Test setindex!" begin
19+
ct["b"] = 2
20+
@test ct["b"] == 2
21+
ct["b"] = 0
22+
@test ct["b"] == 0
23+
end
2124

22-
@testset "Test inc!" begin
23-
inc!(ct, "a")
24-
@test haskey(ct, "a")
25-
@test ct["a"] == 1
25+
@testset "Test inc!" begin
26+
inc!(ct, "a")
27+
@test haskey(ct, "a")
28+
@test ct["a"] == 1
2629

27-
inc!(ct, "b", 2)
28-
@test haskey(ct, "b")
29-
@test ct["b"] == 2
30-
end
30+
inc!(ct, "b", 2)
31+
@test haskey(ct, "b")
32+
@test ct["b"] == 2
33+
end
34+
35+
@testset "Test dec!" begin
36+
dec!(ct, "b")
37+
@test ct["b"] == 1
38+
dec!(ct, "b", 16)
39+
@test ct["b"] == -15
40+
ct["b"] = 2
41+
end
42+
43+
@testset "Test convert" begin
44+
inc!(ct, "b", 0x3)
45+
@test ct["b"] == 5
3146

32-
@testset "Test dec!" begin
33-
dec!(ct, "b")
34-
@test ct["b"] == 1
35-
dec!(ct, "b", 16)
36-
@test ct["b"] == -15
37-
ct["b"] = 2
47+
@test !haskey(ct, "abc")
48+
@test ct["abc"] == 0
49+
50+
@test length(ct) == 2
51+
@test length(collect(ct)) == 2
52+
@test length(collect(keys(ct))) == 2
53+
@test length(collect(values(ct))) == 2
54+
@test sum(ct) == 6
55+
end
3856
end
3957

40-
@testset "Test convert" begin
41-
inc!(ct, "b", 0x3)
42-
@test ct["b"] == 5
58+
@testset "pop!" begin
59+
acc = Accumulator(:a=>1, :b=>2, :c=>3)
60+
@test pop!(acc, :c) == 2
61+
@test acc == Accumulator(:a=>1, :b=>2, :c=>2)
4362

44-
@test !haskey(ct, "abc")
45-
@test ct["abc"] == 0
63+
# pop! with default differs from dec!
64+
acc = Accumulator(:a=>1, :b=>2, :c=>3)
65+
@test pop!(acc, :c, 3) == 2 # default, not decrement amount
66+
@test acc == Accumulator(:a=>1, :b=>2, :c=>2)
4667

47-
@test length(ct) == 2
48-
@test length(collect(ct)) == 2
49-
@test length(collect(keys(ct))) == 2
50-
@test length(collect(values(ct))) == 2
51-
@test sum(ct) == 6
68+
acc = Accumulator(:a=>1, :b=>2, :c=>3)
69+
@test pop!(acc, :d, 4) == 4
70+
@test acc == Accumulator(:a=>1, :b=>2, :c=>3)
5271
end
5372

5473
@testset "From Pairs" begin
@@ -71,11 +90,6 @@
7190
@test ct2["a"] == 3
7291
@test ct2["b"] == 2
7392
@test ct2["c"] == 2
74-
75-
merge!(ct, ct2)
76-
@test ct["a"] == 4
77-
@test ct["b"] == 7
78-
@test ct["c"] == 2
7993
end
8094

8195
@testset "From Dict" begin
@@ -260,8 +274,6 @@
260274
@test sprint(show,Accumulator(1 => 3)) == "Accumulator(1 => 3)"
261275
@test sprint(show,Accumulator(1 => 3, 3 => 4)) == "Accumulator(3 => 4, 1 => 3)"
262276
end
263-
264-
265277
end
266278

267279
end # @testset Accumulators

0 commit comments

Comments
 (0)