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

Added properties and propertyvalues iterators #61

Merged
merged 2 commits into from
Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
35 changes: 34 additions & 1 deletion src/IterTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export
ncycle,
ivec,
flagfirst,
takewhile
takewhile,
properties,
propertyvalues

function has_length(it)
it_size = IteratorSize(it)
Expand Down Expand Up @@ -908,4 +910,35 @@ Base.IteratorSize(it::TakeWhile) = Base.SizeUnknown()
eltype(::Type{TakeWhile{I}}) where {I} = eltype(I)
IteratorEltype(::Type{TakeWhile{I}}) where {I} = IteratorEltype(I)

struct Properties{T}
names
rofinn marked this conversation as resolved.
Show resolved Hide resolved
x::T
end

struct PropertyValues{T}
names
x::T
end

length(p::Union{Properties, PropertyValues}) = length(p.names)
IteratorSize(::Type{<:Union{Properties, PropertyValues}}) = HasLength()

properties(x::T) where {T} = Properties{T}(propertynames(x), x)

function iterate(p::Properties, state=1)
state > length(p) && return nothing
rofinn marked this conversation as resolved.
Show resolved Hide resolved

name = p.names[state]
return ((name, getproperty(p.x, name)), state + 1)
end

propertyvalues(x::T) where {T} = PropertyValues{T}(propertynames(x), x)

function iterate(p::PropertyValues, state=1)
state > length(p) && return nothing

name = p.names[state]
return (getproperty(p.x, name), state + 1)
end

end # module IterTools
43 changes: 42 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -407,12 +407,53 @@ include("testing_macros.jl")

@test collect(flagfirst(Int[])) == Tuple{Bool,Int}[]
end

@testset "takewhile" begin
@test collect(takewhile(x -> x^2 < 10, 1:10)) == Any[1, 2, 3]
@test collect(takewhile(x -> x^2 < 10, Iterators.countfrom(1))) == Any[1, 2, 3]
@test collect(takewhile(x -> x^2 < 10, 5:10)) == Any[]
@test collect(takewhile(x -> true, 5:10)) == collect(5:10)
end

@testset "properties" begin
p1 = properties(1 + 2im)
@test IteratorEltype(p1) isa HasEltype
@test eltype(p1) == Any
@test IteratorSize(p1) isa HasLength
@test length(p1) == 2
@test collect(p1) == Any[(:re, 1), (:im, 2)]

ntp = (a = "", b = 1, c = 2.0)
p2 = properties(ntp)
@test collect(p2) == Tuple.(collect(pairs(ntp)))

# HasLength used as an example no-field struct
rofinn marked this conversation as resolved.
Show resolved Hide resolved
p3 = properties(HasLength())
@test collect(p3) == Any[]
end

@testset "propertyvalues" begin
pv1 = propertyvalues(1 + 2im)
@test IteratorEltype(pv1) isa HasEltype
@test eltype(pv1) == Any
@test IteratorSize(pv1) isa HasLength
@test length(pv1) == 2
@test collect(pv1) == Any[1, 2]

tp = ("", 1, 2.0)
pv2 = propertyvalues(tp)

# getproperty for tuples wasn't introduced until 1.2
# https://github.com/JuliaLang/julia/pull/31324
@static if VERSION < v"1.2.0-DEV.460"
@test_broken collect(pv2) == collect(tp)
else
@test collect(pv2) == collect(tp)
end

# HasLength used as an example no-field struct
pv3 = propertyvalues(HasLength())
@test collect(pv3) == Any[]
end
end
end