I was looking at the Julia manual and read about custom iterators. The gist: having defined my own type, once I extend Base.iterate
+ Base.length
+ Base.eltype
to work with my own type, I can do cool stuff.
Here’s the example from the manual, slightly modified:
struct Squares
count::Int
eltype::DataType
function Squares(c::Int,e::DataType)
e <: Real ? new(c,e) : throw(error("only real DataTypes allowed"))
end
end
Base.iterate(s::Squares, state=1) = state > s.count ? nothing : ( s.eltype(state*state), state+1 )
Base.length(s::Squares) = s.count
Base.eltype(s::Squares) = s.eltype # is this the best way to do this?
This let’s me do the following out-of-the-box:
julia> for i in Squares(4,UInt8) println(i) end
1
4
9
16
julia> collect(Squares(3,Rational{Int64}))
3-element Array{Rational{Int64},1}:
1//1
4//1
9//1
julia> 9 in Squares(3,Float32)
true
This is cool stuff!
My question is: is Base.eltype(s::Squares) = s.eltype
the best way to do this? I know the answer is no, quoting from the manual:
The definition
eltype(x) = eltype(typeof(x))
is provided for convenience so that instances can be passed instead of types. However the form that accepts a type argument should be defined for new types.
So what’s the correct syntax for Base.eltype(::Type{Squares}) = Squares.eltype
(which is clearly incorrect!)?
cheers!