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

Add iteration support for more containers #448

Merged
merged 14 commits into from
Jul 22, 2024
Merged
12 changes: 9 additions & 3 deletions src/StdLib/StdDeque.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ Base.IndexStyle(::Type{<:StdDeque}) = IndexLinear()
Base.size(v::StdDeque) = (Int(cppsize(v)),)
Base.getindex(v::StdDeque, i::Int) = cxxgetindex(v, i)[]
Base.setindex!(v::StdDeque{T}, val, i::Int) where {T} = cxxsetindex!(v, convert(T, val), i)
Base.push!(v::StdDeque, x) = push_back!(v, x)
Base.pushfirst!(v::StdDeque, x) = push_front!(v, x)
Base.pushfirst!(v::StdDeque, x) = (push_front!(v, x); v)
Base.push!(v::StdDeque, x) = (isempty(v) ? push_front!(v, x) : push_back!(v, x); v)
Base.pop!(v::StdDeque) = pop_back!(v)
Base.popfirst!(v::StdDeque) = pop_front!(v)
Base.resize!(v::StdDeque, n::Integer) = resize!(v, n)
Base.resize!(v::StdDeque, n::Integer) = resize!(v, n)

Base.:(==)(a::StdDequeIterator, b::StdDequeIterator) = iterator_is_equal(a, b)

_deque_iteration_tuple(v::StdDeque, state::StdDequeIterator) = state == iteratorend(v) ? nothing : (iterator_value(state), state)
Base.iterate(v::StdDeque) = _deque_iteration_tuple(v, iteratorbegin(v))
Base.iterate(v::StdDeque, state::StdDequeIterator) = (state != iteratorend(v)) ? _deque_iteration_tuple(v, iterator_next(state)) : nothing
30 changes: 29 additions & 1 deletion src/StdLib/StdForwardList.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,32 @@ Base.isempty(v::StdForwardList) = flist_isempty(v)
Base.first(v::StdForwardList) = flist_front(v)
Base.empty!(v::StdForwardList) = (flist_empty!(v); v)
Base.pushfirst!(v::StdForwardList, x) = (flist_push_front!(v, x); v)
Base.popfirst!(v::StdForwardList) = (flist_pop_front!(v); v)
Base.popfirst!(v::StdForwardList) = (flist_pop_front!(v); v)

Base.:(==)(a::StdForwardListIterator, b::StdForwardListIterator) = iterator_is_equal(a, b)
_forward_list_iteration_tuple(v::StdForwardList, state::StdForwardListIterator) = (state == iteratorend(v)) ? nothing : (iterator_value(state), state)
Base.iterate(v::StdForwardList) = _forward_list_iteration_tuple(v, iteratorbegin(v))
Base.iterate(v::StdForwardList, state::StdForwardListIterator) = (state != iteratorend(v)) ? _forward_list_iteration_tuple(v, iterator_next(state)) : nothing

function Base.show(io::IO, ::MIME"text/plain", container::StdForwardList{T}) where {T}
print(io, "StdForwardList{", T, "}")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather go for something like:

StdForwardList{<element type>} with X elements:
  2
  3
  1

similar to the way Julia Sets are printed. The [] syntax risks confusion with arrays.

Copy link
Contributor Author

@PraneethJain PraneethJain Jul 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a forward list, printing the length will require iterating over the entire list, so I have omitted the number of elements and now gone for this:

StdForwardList{Int64}:
  2
  3
  1


iterator = iterate(container)
if iterator === nothing
print(io, "()")
return
end

print(io, ":")
count = 0
while iterator !== nothing && count < 10
item, state = iterator
print(io, "\n ", item)
iterator = iterate(container, state)
count += 1
end

if iterator !== nothing
print(io, "\n ⋮")
end
end
20 changes: 20 additions & 0 deletions src/StdLib/StdList.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,23 @@ Base.push!(v::StdList, x) = (list_push_back!(v, x); v)
Base.pushfirst!(v::StdList, x) = (list_push_front!(v, x); v)
Base.pop!(v::StdList) = (list_pop_back!(v); v)
Base.popfirst!(v::StdList) = (list_pop_front!(v); v)


Base.:(==)(a::StdListIterator, b::StdListIterator) = iterator_is_equal(a, b)
_list_iteration_tuple(v::StdList, state::StdListIterator) = (state == iteratorend(v)) ? nothing : (iterator_value(state), state)
Base.iterate(v::StdList) = _list_iteration_tuple(v, iteratorbegin(v))
Base.iterate(v::StdList, state::StdListIterator) = (state != iteratorend(v)) ? _list_iteration_tuple(v, iterator_next(state)) : nothing

function Base.show(io::IO, ::MIME"text/plain", container::StdList{T}) where {T}
n = length(container)
print(io, "StdList{", T, "} with ", n, " element", n == 1 ? "" : "s")

n == 0 && return
print(io, ":")
for item in Iterators.take(container, 10)
print(io, "\n ", item)
end
if n > 10
print(io, "\n ⋮")
end
end
12 changes: 11 additions & 1 deletion src/StdLib/StdMultisetTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,14 @@ for StdMultisetType in (StdMultiset, StdUnorderedMultiset)
Base.in(x, v::StdMultisetType) = multiset_in(v, x)
Base.delete!(v::StdMultisetType, x) = (multiset_delete!(v, x); v)
Base.count(x, v::StdMultisetType) = multiset_count(v, x)
end
end

Base.:(==)(a::StdMultisetIterator, b::StdMultisetIterator) = iterator_is_equal(a, b)
_multiset_iteration_tuple(v::StdMultiset, state::StdMultisetIterator) = (state == iteratorend(v)) ? nothing : (iterator_value(state), state)
Base.iterate(v::StdMultiset) = _multiset_iteration_tuple(v, iteratorbegin(v))
Base.iterate(v::StdMultiset, state::StdMultisetIterator) = (state != iteratorend(v)) ? _multiset_iteration_tuple(v, iterator_next(state)) : nothing

Base.:(==)(a::StdUnorderedMultisetIterator, b::StdUnorderedMultisetIterator) = iterator_is_equal(a, b)
_unordered_multiset_iteration_tuple(v::StdUnorderedMultiset, state::StdUnorderedMultisetIterator) = (state == iteratorend(v)) ? nothing : (iterator_value(state), state)
Base.iterate(v::StdUnorderedMultiset) = _unordered_multiset_iteration_tuple(v, iteratorbegin(v))
Base.iterate(v::StdUnorderedMultiset, state::StdUnorderedMultisetIterator) = (state != iteratorend(v)) ? _unordered_multiset_iteration_tuple(v, iterator_next(state)) : nothing
12 changes: 11 additions & 1 deletion src/StdLib/StdSetTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,14 @@ for StdSetType in (StdSet, StdUnorderedSet)
Base.push!(v::StdSetType, x) = (set_insert!(v, x); v)
Base.in(x, v::StdSetType) = set_in(v, x)
Base.delete!(v::StdSetType, x) = (set_delete!(v, x); v)
end
end

Base.:(==)(a::StdSetIterator, b::StdSetIterator) = iterator_is_equal(a, b)
_set_iteration_tuple(v::StdSet, state::StdSetIterator) = (state == iteratorend(v)) ? nothing : (iterator_value(state), state)
Base.iterate(v::StdSet) = _set_iteration_tuple(v, iteratorbegin(v))
Base.iterate(v::StdSet, state::StdSetIterator) = (state != iteratorend(v)) ? _set_iteration_tuple(v, iterator_next(state)) : nothing

Base.:(==)(a::StdUnorderedSetIterator, b::StdUnorderedSetIterator) = iterator_is_equal(a, b)
_unordered_set_iteration_tuple(v::StdUnorderedSet, state::StdUnorderedSetIterator) = (state == iteratorend(v)) ? nothing : (iterator_value(state), state)
Base.iterate(v::StdUnorderedSet) = _unordered_set_iteration_tuple(v, iteratorbegin(v))
Base.iterate(v::StdUnorderedSet, state::StdUnorderedSetIterator) = (state != iteratorend(v)) ? _unordered_set_iteration_tuple(v, iterator_next(state)) : nothing
44 changes: 41 additions & 3 deletions test/stdlib.jl
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,16 @@ let
deque1 = StdDeque{Int64}()
@test length(deque1) == 0
push!(deque1, 7)
push!(deque1, 9)
deque1 = push!(deque1, 9)
@test length(deque1) == 2
for (i, x) in enumerate(deque1)
if i == 1
@test x == 7
elseif i == 2
@test x == 9
end
end
@test sum(deque1) == 16
deque2 = deque1
popfirst!(deque2)
@test length(deque2) == 1
Expand Down Expand Up @@ -410,6 +418,7 @@ end
@test length(set) == 2
@test (10 ∈ set) == true
@test (20 ∈ set) == true
@test Set(set) == Set([10, 20]) # Tests the iterators
set = delete!(set, 20)
@test length(set) == 1
@test (20 ∈ set) == false
Expand Down Expand Up @@ -463,6 +472,15 @@ end
@test length(multiset) == 3
@test (10 ∈ multiset) == true
@test (20 ∈ multiset) == true
ten_count = 0
twenty_count = 0
# Tests the iterators
for x in multiset
ten_count += x == 10
twenty_count += x == 20
end
@test ten_count == 1
@test twenty_count == 2
multiset = delete!(multiset, 20)
@test length(multiset) == 1
@test (20 ∈ multiset) == false
Expand Down Expand Up @@ -518,6 +536,16 @@ end
list = pushfirst!(list, StdString("cd"))
list = push!(list, StdString("ef"))
@test length(list) == 3
for (i, x) in enumerate(list)
if i == 1
@test x == "cd"
elseif i == 2
@test x == "ab"
elseif i == 3
@test x == "ef"
end
end
@test prod(list) == "cdabef"
@test first(list) == "cd"
@test last(list) == "ef"
list = pop!(list)
Expand Down Expand Up @@ -547,20 +575,30 @@ end

@testset "StdForwardList" begin
@testset "StdForwardList with integers" begin
forwardlist = StdList{Int64}()
forwardlist = StdForwardList{Int64}()
@test isempty(forwardlist) == true
forwardlist = pushfirst!(forwardlist, 10)
pushfirst!(forwardlist, 20)
@test first(forwardlist) == 20
for (i, x) in enumerate(forwardlist)
if i == 1
@test x == 20
elseif i == 2
@test x == 10
end
end
forwardlist = popfirst!(forwardlist)
@test first(forwardlist) == 10
for x in forwardlist
@test x == 10
end
@test isempty(forwardlist) == false
forwardlist = empty!(forwardlist)
@test isempty(forwardlist) == true
end

@testset "StdForwardList with StdString" begin
forwardlist = StdList{StdString}()
forwardlist = StdForwardList{StdString}()
@test isempty(forwardlist) == true
forwardlist = pushfirst!(forwardlist, StdString("ab"))
pushfirst!(forwardlist, StdString("cd"))
Expand Down
Loading