Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with new iteration protocol #382

Merged
merged 3 commits into from
May 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/accumulator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ sum(ct::Accumulator) = sum(values(ct.map))
start(ct::Accumulator) = start(ct.map)
next(ct::Accumulator, state) = next(ct.map, state)
done(ct::Accumulator, state) = done(ct.map, state)

if isdefined(Base, :LegacyIterationCompat)
# resolve ambiguity
next(ct::Accumulator, state::Base.LegacyIterationCompat{I,T,S}) where {I>:Accumulator,T,S} = next(ct.map, state)
done(ct::Accumulator, state::Base.LegacyIterationCompat{I,T,S}) where {I>:Accumulator,T,S} = done(ct.map, state)
end

# manipulation

Expand Down
4 changes: 2 additions & 2 deletions src/circ_deque.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ end

# Iteration via getindex
@inline Base.start(d::CircularDeque) = 1
@inline Base.next(d::CircularDeque, i) = (_unsafe_getindex(d, i), i+1)
@inline Base.done(d::CircularDeque, i) = i == d.n + 1
@inline Base.next(d::CircularDeque, i::Int) = (_unsafe_getindex(d, i), i+1)
@inline Base.done(d::CircularDeque, i::Int) = i == d.n + 1

function Base.show(io::IO, D::CircularDeque{T}) where T
print(io, "CircularDeque{$T}([")
Expand Down
5 changes: 5 additions & 0 deletions src/classified_collections.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ keys(cc::ClassifiedCollections) = keys(cc.map)
start(cc::ClassifiedCollections) = start(cc.map)
next(cc::ClassifiedCollections, state) = next(cc.map, state)
done(cc::ClassifiedCollections, state) = done(cc.map, state)
if isdefined(Base, :LegacyIterationCompat)
# resolve ambiguity
next(ct::ClassifiedCollections, state::Base.LegacyIterationCompat{I,T,S}) where {I>:ClassifiedCollections,T,S} = next(ct.map, state)
done(ct::ClassifiedCollections, state::Base.LegacyIterationCompat{I,T,S}) where {I>:ClassifiedCollections,T,S} = done(ct.map, state)
end

# manipulation

Expand Down
12 changes: 11 additions & 1 deletion src/default_dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ DefaultDictBase{K,V}(default::F; kwargs...) where {K,V,F} = DefaultDictBase{K,V,
# most functions are simply delegated to the wrapped dictionary
@delegate DefaultDictBase.d [ get, haskey, getkey, pop!,
start, done, next, isempty, length ]
if isdefined(Base, :LegacyIterationCompat)
# resolve ambiguity
next(d::DefaultDictBase, state::Base.LegacyIterationCompat{I,T,S}) where {I>:DefaultDictBase,T,S} = next(d.d, state)
done(d::DefaultDictBase, state::Base.LegacyIterationCompat{I,T,S}) where {I>:DefaultDictBase,T,S} = done(d.d, state)
end

# Some functions are delegated, but then need to return the main dictionary
# NOTE: push! is not included below, because the fallback version just
Expand All @@ -66,7 +71,7 @@ else
in(key, v::Base.KeyIterator{T}) where {T<:DefaultDictBase} = key in keys(v.dict.d)
next(v::Base.KeyIterator{T}, i) where {T<:DefaultDictBase} = (v.dict.d.keys[i], Base.skip_deleted(v.dict.d,i+1))
end
next(v::Base.ValueIterator{T}, i) where {T<:DefaultDictBase} = (v.dict.d.vals[i], Base.skip_deleted(v.dict.d,i+1))
next(v::Base.ValueIterator{T}, i::Int) where {T<:DefaultDictBase} = (v.dict.d.vals[i], Base.skip_deleted(v.dict.d,i+1))

getindex(d::DefaultDictBase, key) = get!(d.d, key, d.default)

Expand Down Expand Up @@ -130,6 +135,11 @@ for _Dict in [:Dict, :OrderedDict]
@delegate $DefaultDict.d [ getindex, get, get!, haskey,
getkey, pop!, start, next,
done, isempty, length ]
if isdefined(Base, :LegacyIterationCompat)
# resolve ambiguity
next(d::$DefaultDict, state::Base.LegacyIterationCompat{I,T,S}) where {I>:$DefaultDict,T,S} = next(d.d, state)
done(d::$DefaultDict, state::Base.LegacyIterationCompat{I,T,S}) where {I>:$DefaultDict,T,S} = done(d.d, state)
end

# Some functions are delegated, but then need to return the main dictionary
# NOTE: push! is not included below, because the fallback version just
Expand Down
12 changes: 6 additions & 6 deletions src/deque.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ end

start(qi::DequeIterator{T}) where {T} = (qi.q.head, qi.q.head.front)

function next(qi::DequeIterator{T}, s) where T
function next(qi::DequeIterator{T}, s::Tuple) where T
cb = s[1]
i = s[2]
x = cb.data[i]
Expand All @@ -129,7 +129,7 @@ function next(qi::DequeIterator{T}, s) where T
(x, (cb, i))
end

done(q::DequeIterator{T}, s) where {T} = (s[2] > s[1].back)
done(q::DequeIterator{T}, s::Tuple) where {T} = (s[2] > s[1].back)

# Backwards deque iteration

Expand All @@ -141,9 +141,9 @@ start(qi::ReverseDequeIterator{T}) where {T} = (qi.q.rear, qi.q.rear.back)

# We're finished when our index is less than the first index
# of the current block (which can only happen on the first block)
done(qi::ReverseDequeIterator{T}, s) where {T} = (s[2] < s[1].front)
done(qi::ReverseDequeIterator{T}, s::Tuple) where {T} = (s[2] < s[1].front)

function next(qi::ReverseDequeIterator{T}, s) where T
function next(qi::ReverseDequeIterator{T}, s::Tuple) where T
cb = s[1]
i = s[2]
x = cb.data[i]
Expand All @@ -161,8 +161,8 @@ end
reverse_iter(q::Deque{T}) where {T} = ReverseDequeIterator{T}(q)

start(q::Deque{T}) where {T} = start(DequeIterator{T}(q))
next(q::Deque{T}, s) where {T} = next(DequeIterator{T}(q), s)
done(q::Deque{T}, s) where {T} = done(DequeIterator{T}(q), s)
next(q::Deque{T}, s::Tuple) where {T} = next(DequeIterator{T}(q), s)
done(q::Deque{T}, s::Tuple) where {T} = done(DequeIterator{T}(q), s)

Base.length(qi::DequeIterator{T}) where {T} = qi.q.len
Base.length(qi::ReverseDequeIterator{T}) where {T} = qi.q.len
Expand Down
4 changes: 2 additions & 2 deletions src/int_set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ end

# Use the next-set index as the state to prevent looking it up again in done
start(s::IntSet) = next(s, 0)[2]
function next(s::IntSet, i, invert=false)
function next(s::IntSet, i::Int, invert=false)
if s.inverse ⊻ invert
# i+1 could rollover causing a BoundsError in findnext/findnextnot
nextidx = i == typemax(Int) ? 0 : coalesce(findnextnot(s.bits, i+1), 0)
Expand All @@ -188,7 +188,7 @@ function next(s::IntSet, i, invert=false)
end
(i-1, nextidx)
end
done(s::IntSet, i) = i <= 0
done(s::IntSet, i::Int) = i <= 0

# Nextnot iterates through elements *not* in the set
nextnot(s::IntSet, i) = next(s, i, true)
Expand Down
9 changes: 7 additions & 2 deletions src/multi_dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ end
@delegate MultiDict.d [ haskey, get, get!, getkey,
getindex, length, isempty, eltype,
start, next, done, keys, values]
if isdefined(Base, :LegacyIterationCompat)
# resolve ambiguity
next(d::MultiDict, state::Base.LegacyIterationCompat{I,T,S}) where {I>:MultiDict,T,S} = next(d.d, state)
done(d::MultiDict, state::Base.LegacyIterationCompat{I,T,S}) where {I>:MultiDict,T,S} = done(d.d, state)
end

sizehint!(d::MultiDict, sz::Integer) = (sizehint!(d.d, sz); d)
copy(d::MultiDict) = MultiDict(d)
Expand Down Expand Up @@ -110,12 +115,12 @@ function start(e::EnumerateAll)
(start(e.d.d), nothing, vs, start(vs))
end

function done(e::EnumerateAll, s)
function done(e::EnumerateAll, s::Tuple)
dst, k, vs, vst = s
done(vs, vst) && done(e.d.d, dst)
end

function next(e::EnumerateAll, s)
function next(e::EnumerateAll, s::Tuple)
dst, k, vs, vst = s
while done(vs, vst)
((k, vs), dst) = next(e.d.d, dst)
Expand Down
6 changes: 3 additions & 3 deletions src/ordered_dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -426,15 +426,15 @@ function start(t::OrderedDict)
t.ndel > 0 && rehash!(t)
1
end
done(t::OrderedDict, i) = done(t.keys, i)
next(t::OrderedDict, i) = (Pair(t.keys[i],t.vals[i]), i+1)
done(t::OrderedDict, i::Int) = i > length(t.keys)
next(t::OrderedDict, i::Int) = (Pair(t.keys[i],t.vals[i]), i+1)

if isdefined(Base, :KeySet) # 0.7.0-DEV.2722
next(v::Base.KeySet{K,T}, i) where {K,T<:OrderedDict{K}} = (v.dict.keys[i], i+1)
else
next(v::Base.KeyIterator{T}, i) where {T<:OrderedDict} = (v.dict.keys[i], i+1)
end
next(v::ValueIterator{T}, i) where {T<:OrderedDict} = (v.dict.vals[i], i+1)
next(v::ValueIterator{T}, i::Int) where {T<:OrderedDict} = (v.dict.vals[i], i+1)

function merge(d::OrderedDict, others::AbstractDict...)
K, V = keytype(d), valtype(d)
Expand Down
4 changes: 2 additions & 2 deletions src/ordered_set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ copy(s::OrderedSet) = union!(similar(s), s)
empty!(s::OrderedSet{T}) where {T} = (empty!(s.dict); s)

start(s::OrderedSet) = start(s.dict)
done(s::OrderedSet, state) = done(s.dict, state)
done(s::OrderedSet, state::Int) = done(s.dict, state)
# NOTE: manually optimized to take advantage of OrderedDict representation
next(s::OrderedSet, i) = (s.dict.keys[i], i+1)
next(s::OrderedSet, i::Int) = (s.dict.keys[i], i+1)

pop!(s::OrderedSet) = pop!(s.dict)[1]

Expand Down
9 changes: 9 additions & 0 deletions src/priorityqueue.jl
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,12 @@ function next(pq::PriorityQueue{K,V}, i) where {K,V}
(k, idx), i = next(pq.index, i)
return (pq.xs[idx], i)
end

if isdefined(Base, :LegacyIterationCompat)
# resolve ambiguity
done(ct::PriorityQueue, i::Base.LegacyIterationCompat{I,T,S}) where {I>:PriorityQueue,T,S} = done(pq.index, i)
function next(ct::PriorityQueue{K,V}, i::Base.LegacyIterationCompat{I,T,S}) where {K,V,I>:PriorityQueue{K,V},T,S}
(k, idx), i = next(pq.index, i)
return (pq.xs[idx], i)
end
end
4 changes: 2 additions & 2 deletions src/queue.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ dequeue!(s::Queue) = popfirst!(s.store)
# Iterators

start(q::Queue) = start(q.store)
next(q::Queue, s) = next(q.store, s)
done(q::Queue, s) = done(q.store, s)
next(q::Queue, s::Tuple) = next(q.store, s)
done(q::Queue, s::Tuple) = done(q.store, s)

reverse_iter(q::Queue) = reverse_iter(q.store)
4 changes: 2 additions & 2 deletions src/stack.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pop!(s::Stack) = pop!(s.store)
empty!(s::Stack) = (empty!(s.store); s)

start(st::Stack) = start(reverse_iter(st.store))
next(st::Stack, s) = next(reverse_iter(st.store), s)
done(st::Stack, s) = done(reverse_iter(st.store), s)
next(st::Stack, s::Tuple) = next(reverse_iter(st.store), s)
done(st::Stack, s::Tuple) = done(reverse_iter(st.store), s)

reverse_iter(s::Stack{T}) where {T} = DequeIterator{T}(s.store)
4 changes: 2 additions & 2 deletions src/trie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,15 @@ end
# since the root of the trie corresponds to a length 0 prefix of str.
start(it::TrieIterator) = (it.t, 0)

function next(it::TrieIterator, state)
function next(it::TrieIterator, state::Tuple)
t, i = state
i == 0 && return it.t, (it.t, 1)

t = t.children[it.str[i]]
return (t, (t, i + 1))
end

function done(it::TrieIterator, state)
function done(it::TrieIterator, state::Tuple)
t, i = state
i == 0 && return false
i == length(it.str) + 1 && return true
Expand Down
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ using Compat
using Compat.Test
using Compat.Random
using Compat.Serialization
using Primes

import DataStructures: IntSet

@test isempty(detect_ambiguities(Base, Core, DataStructures))

using Primes

tests = ["int_set",
"deque",
"circ_deque",
Expand Down