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

[RFC] Adding component iterator #190

Open
kimikage opened this issue Apr 22, 2020 · 6 comments
Open

[RFC] Adding component iterator #190

kimikage opened this issue Apr 22, 2020 · 6 comments

Comments

@kimikage
Copy link
Collaborator

This is a PoC to clarify the discussion in #184, and is the modernized (Julia v1) version of #7. See also #119

using ColorTypes
import ColorTypes.ColorantN

struct ComponentIterator{C<:Colorant}
    c::C
end

function Base.getproperty(c::C, sym::Symbol) where C <: Colorant
   if sym === :components
      return ComponentIterator{C}(c)
   else # fallback to getfield
      return getfield(c, sym)
   end
end

Base.eltype(itr::ComponentIterator{C}) where {T, C <: Colorant{T}} = T
Base.length(itr::ComponentIterator{C}) where {N, C <: ColorantN{N}} = N

function Base.iterate(itr::ComponentIterator{C}, state::Int=0) where {N, C <: ColorantN{N}}
    state >= N && return nothing
    state += 1
    (itr[state], state)
end

function Base.getindex(itr::ComponentIterator{C}, i::Integer) where {N, C <: ColorantN{N}}
    comp_n = (comp1, comp2, comp3) # FIXME
    (comp_n[i])(itr.c)
end
julia> rgb_f32 = RGB{Float32}(1.0, 0.5, 0.0)
RGB{Float32}(1.0f0,0.5f0,0.0f0)

julia> eltype(rgb_f32.components)
Float32

julia> length(rgb_f32.components)
3

julia> for c in rgb_f32.components
           @show c
       end
c = 1.0f0
c = 0.5f0
c = 0.0f0

julia> rgb_f32.components[2]
0.5f0

julia> RGB((RGB(1.0, 0.5, 0.0).components .+ RGB(0.0, 0.1, 0.2).components)...)
RGB{Float64}(1.0,0.6,0.2)

The above has some problems in practical use, but IMO, it is better than eltypec and lengthc.

@kimikage
Copy link
Collaborator Author

kimikage commented Apr 22, 2020

It maight be a good idea to create a new package ColorComponentIterators.jl, as ColorVectorSpace.jl is a separate package.
In fact, such a simple iterator, mapc, and so on are not very useful (cf. #184 (comment)). More complex iterators may be needed.

@timholy
Copy link
Member

timholy commented Apr 22, 2020

With constant propagation this might be more useful than previously, and hiding it behind a c.components seems like a pretty clever design. Thanks for submitting this, I will have to think through the implications.

@kimikage
Copy link
Collaborator Author

kimikage commented Apr 24, 2021

The problem with providing the iteration interface as a function instead of a property is name collision.
The components is not a color-specific concept. At least, Distributions exports the components. (Of course, I don't think Distributions must have a monopoly on the function.)
https://github.com/JuliaStats/Distributions.jl/blob/a36c613f5434c76ef21d3ed2d4a80fab66068d19/src/Distributions.jl#L178

comps is short, and the risk of name clashes seems to be sufficiently low. It is not easy to understand, though.

@johnnychen94
Copy link
Member

Base has fieldnames and fieldtypes for DataType, do you think fields a good name for the instance x::Colorant? We could possibly propose this name and the iterator implementation in Julia Base.

@kimikage
Copy link
Collaborator Author

kimikage commented Apr 24, 2021

Thanks for the suggestion.
However, as you say the "fields" is already used as fields of the structure; the difference between ARGB and RGBA or types like ARGB32 will bring confusion.

@kimikage kimikage mentioned this issue May 6, 2021
19 tasks
@kimikage
Copy link
Collaborator Author

The feature itself has been implemented in PR #260, but the design of the public API is still not settled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants