Skip to content

Commit

Permalink
Add FieldValues iterator (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
iamed2 authored Jul 4, 2019
1 parent a2e4d09 commit 2104784
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
8 changes: 8 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,11 @@ Iterate over struct or named tuple property values.
```@docs
propertyvalues
```

## fieldvalues(x)

Like `(getfield(x, i) for i in 1:nfields(x))` but faster.

```@docs
fieldvalues
```
36 changes: 35 additions & 1 deletion src/IterTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export
flagfirst,
takewhile,
properties,
propertyvalues
propertyvalues,
fieldvalues

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

# Properties

struct Properties{T}
x::T
n::Int
Expand Down Expand Up @@ -940,6 +943,8 @@ function iterate(p::Properties, state=1)
return ((name, getproperty(p.x, name)), state + 1)
end

# PropertyValues

struct PropertyValues{T}
x::T
n::Int
Expand All @@ -958,6 +963,7 @@ julia> collect(propertyvalues(1 + 2im))
2
```
"""

function propertyvalues(x::T) where T
names = propertynames(x)
return PropertyValues{T}(x, length(names), names)
Expand All @@ -973,4 +979,32 @@ end
length(p::Union{Properties, PropertyValues}) = p.n
IteratorSize(::Type{<:Union{Properties, PropertyValues}}) = HasLength()

# FieldValues

struct FieldValues{T}
x::T
end

"""
fieldvalues(x)
Iterate through the values of the fields of `x`.
```jldoctest
julia> collect(fieldvalues(1 + 2im))
2-element Array{Any,1}:
1
2
```
"""
fieldvalues(x::T) where {T} = FieldValues{T}(x)
length(fs::FieldValues{T}) where {T} = fieldcount(T)
IteratorSize(::Type{<:FieldValues}) = HasLength()

function iterate(fs::FieldValues, state=1)
state > length(fs) && return nothing

return (getfield(fs.x, state), state + 1)
end

end # module IterTools
17 changes: 17 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -455,5 +455,22 @@ include("testing_macros.jl")
pv3 = propertyvalues(HasLength())
@test collect(pv3) == Any[]
end

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

tp = ("", 1, 2.0)
fv2 = fieldvalues(tp)
@test collect(fv2) == collect(tp)

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

0 comments on commit 2104784

Please sign in to comment.