From 3630dd3146af304cc40b038760d4062a0b282d18 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 1 Mar 2016 16:42:07 -0500 Subject: [PATCH] more iterator trait declarations make HasEltype and HasLength the default --- base/channels.jl | 2 ++ base/dict.jl | 3 --- base/generator.jl | 10 ++++------ base/io.jl | 2 ++ base/iterator.jl | 10 ++++++++-- base/libgit2/reference.jl | 2 ++ base/libgit2/walker.jl | 2 ++ base/multidimensional.jl | 11 +++++++---- base/regex.jl | 1 + base/task.jl | 2 ++ test/abstractarray.jl | 1 + test/simdloop.jl | 8 ++++---- test/unicode/utf8proc.jl | 2 +- 13 files changed, 36 insertions(+), 20 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 34778b1585b3a..2362b5742a900 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -95,3 +95,5 @@ function done(c::Channel, state::Ref) end end next{T}(c::Channel{T}, state) = (v=get(state[]); state[]=nothing; (v, state)) + +iteratorsize{C<:Channel}(::Type{C}) = SizeUnknown() diff --git a/base/dict.jl b/base/dict.jl index 80ef8a2c4a45a..c3d4ee24a8745 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -4,9 +4,6 @@ abstract Associative{K,V} -iteratorsize{T<:Associative}(::Type{T}) = HasLength() -iteratoreltype{T<:Associative}(::Type{T}) = HasEltype() - const secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__ haskey(d::Associative, k) = in(k,keys(d)) diff --git a/base/generator.jl b/base/generator.jl index cce7238c83601..efc867a08f5ea 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -26,9 +26,10 @@ abstract IteratorSize immutable SizeUnknown <: IteratorSize end immutable HasLength <: IteratorSize end immutable HasShape <: IteratorSize end +immutable IsInfinite <: IteratorSize end iteratorsize(x) = iteratorsize(typeof(x)) -iteratorsize(::Type) = SizeUnknown() +iteratorsize(::Type) = HasLength() # HasLength is the default and_iteratorsize{T}(isz::T, ::T) = isz and_iteratorsize(::HasLength, ::HasShape) = HasLength() @@ -40,19 +41,16 @@ immutable EltypeUnknown <: IteratorEltype end immutable HasEltype <: IteratorEltype end iteratoreltype(x) = iteratoreltype(typeof(x)) -iteratoreltype(::Type) = EltypeUnknown() +iteratoreltype(::Type) = HasEltype() # HasEltype is the default and_iteratoreltype{T}(iel::T, ::T) = iel and_iteratoreltype(a, b) = EltypeUnknown() iteratorsize{T<:AbstractArray}(::Type{T}) = HasShape() -iteratorsize{T<:AbstractString}(::Type{T}) = HasLength() -iteratorsize{T<:Tuple}(::Type{T}) = HasLength() iteratorsize{I,F}(::Type{Generator{I,F}}) = iteratorsize(I) length(g::Generator) = length(g.iter) size(g::Generator) = size(g.iter) -iteratoreltype{T<:AbstractArray}(::Type{T}) = HasEltype() -iteratoreltype{T<:AbstractString}(::Type{T}) = HasEltype() +iteratoreltype{I,T}(::Type{Generator{I,T}}) = EltypeUnknown() iteratoreltype{I,T}(::Type{Generator{I,Type{T}}}) = HasEltype() eltype{I,T}(::Type{Generator{I,Type{T}}}) = T diff --git a/base/io.jl b/base/io.jl index fd7db0f1daaef..2ea4533fa4b39 100644 --- a/base/io.jl +++ b/base/io.jl @@ -378,6 +378,8 @@ eltype(::Type{EachLine}) = ByteString readlines(s=STDIN) = collect(eachline(s)) +iteratorsize(::Type{EachLine}) = SizeUnknown() + # IOStream Marking # Note that these functions expect that io.mark exists for # the concrete IO type. This may not be true for IO types diff --git a/base/iterator.jl b/base/iterator.jl index e08162297f43b..0323aa1548148 100644 --- a/base/iterator.jl +++ b/base/iterator.jl @@ -125,6 +125,7 @@ done(f::Filter, s) = s[1] eltype{I}(::Type{Filter{I}}) = eltype(I) iteratoreltype{F,I}(::Type{Filter{F,I}}) = iteratoreltype(I) +iteratorsize{T<:Filter}(::Type{T}) = SizeUnknown() # Rest -- iterate starting at the given state @@ -140,6 +141,7 @@ done(i::Rest, st) = done(i.itr, st) eltype{I}(::Type{Rest{I}}) = eltype(I) iteratoreltype{I,S}(::Type{Rest{I,S}}) = iteratoreltype(I) +iteratorsize{T<:Rest}(::Type{T}) = SizeUnknown() # Count -- infinite counting @@ -152,12 +154,13 @@ countfrom(start::Number) = Count(start, one(start)) countfrom() = Count(1, 1) eltype{S}(::Type{Count{S}}) = S -iteratoreltype{I<:Count}(::Type{I}) = HasEltype() start(it::Count) = it.start next(it::Count, state) = (state, state + it.step) done(it::Count, state) = false +iteratorsize{S}(::Type{Count{S}}) = IsInfinite() + # Take -- iterate through the first n elements immutable Take{I} @@ -168,6 +171,7 @@ take(xs, n::Int) = Take(xs, n) eltype{I}(::Type{Take{I}}) = eltype(I) iteratoreltype{I}(::Type{Take{I}}) = iteratoreltype(I) +iteratorsize{T<:Take}(::Type{T}) = SizeUnknown() # TODO start(it::Take) = (it.n, start(it.xs)) @@ -192,6 +196,7 @@ drop(xs, n::Int) = Drop(xs, n) eltype{I}(::Type{Drop{I}}) = eltype(I) iteratoreltype{I}(::Type{Drop{I}}) = iteratoreltype(I) +iteratorsize{T<:Drop}(::Type{T}) = SizeUnknown() # TODO function start(it::Drop) xs_state = start(it.xs) @@ -217,6 +222,7 @@ cycle(xs) = Cycle(xs) eltype{I}(::Type{Cycle{I}}) = eltype(I) iteratoreltype{I}(::Type{Cycle{I}}) = iteratoreltype(I) +iteratorsize{I}(::Type{Cycle{I}}) = IsInfinite() function start(it::Cycle) s = start(it.xs) @@ -241,7 +247,7 @@ immutable Repeated{O} end repeated(x) = Repeated(x) eltype{O}(::Type{Repeated{O}}) = O -iteratoreltype{O}(::Type{Repeated{O}}) = HasEltype() +iteratorsize{O}(::Type{Repeated{O}}) = IsInfinite() start(it::Repeated) = nothing next(it::Repeated, state) = (it.x, nothing) done(it::Repeated, state) = false diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index 38081e3634492..23119c1478baa 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -181,6 +181,8 @@ function Base.next(bi::GitBranchIter, state) return (state[1:2], (GitReference(ref_ptr_ptr[]), btype[1], false)) end +Base.iteratorsize(::Type{GitBranchIter}) = Base.SizeUnknown() + function Base.map(f::Function, bi::GitBranchIter) res = nothing s = start(bi) diff --git a/base/libgit2/walker.jl b/base/libgit2/walker.jl index 9bf2fa93529df..1d564c3c406db 100644 --- a/base/libgit2/walker.jl +++ b/base/libgit2/walker.jl @@ -25,6 +25,8 @@ function Base.next(w::GitRevWalker, state) return (state[1], (id_ptr[], false)) end +Base.iteratorsize(::Type{GitRevWalker}) = Base.SizeUnknown() + function push_head!(w::GitRevWalker) @check ccall((:git_revwalk_push_head, :libgit2), Cint, (Ptr{Void},), w.ptr) return w diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 7ba32048f70b6..37fc21a182d77 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -3,7 +3,7 @@ ### Multidimensional iterators module IteratorsMD -import Base: eltype, length, start, done, next, last, getindex, setindex!, linearindexing, min, max, eachindex, ndims +import Base: eltype, length, size, start, done, next, last, getindex, setindex!, linearindexing, min, max, eachindex, ndims, iteratorsize importall ..Base.Operators import Base: simd_outer_range, simd_inner_length, simd_index, @generated import Base: @nref, @ncall, @nif, @nexprs, LinearFast, LinearSlow, to_index, AbstractCartesianIndex @@ -103,6 +103,7 @@ end end eltype{I}(::Type{CartesianRange{I}}) = I +iteratorsize{I}(::Type{CartesianRange{I}}) = Base.HasShape() @generated function start{I<:CartesianIndex}(iter::CartesianRange{I}) N = length(I) @@ -135,13 +136,15 @@ start{I<:CartesianIndex{0}}(iter::CartesianRange{I}) = false next{I<:CartesianIndex{0}}(iter::CartesianRange{I}, state) = iter.start, true done{I<:CartesianIndex{0}}(iter::CartesianRange{I}, state) = state -@generated function length{I<:CartesianIndex}(iter::CartesianRange{I}) +@generated function size{I<:CartesianIndex}(iter::CartesianRange{I}) N = length(I) - N == 0 && return 1 + N == 0 && return () args = [:(iter.stop[$i]-iter.start[$i]+1) for i=1:N] - Expr(:call,:*,args...) + Expr(:tuple,args...) end +length(iter::CartesianRange) = prod(size(iter)) + last(iter::CartesianRange) = iter.stop @generated function simd_outer_range{I}(iter::CartesianRange{I}) diff --git a/base/regex.jl b/base/regex.jl index 5898349717c85..711df7a207f08 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -327,6 +327,7 @@ compile(itr::RegexMatchIterator) = (compile(itr.regex); itr) eltype(::Type{RegexMatchIterator}) = RegexMatch start(itr::RegexMatchIterator) = match(itr.regex, itr.string, 1, UInt32(0)) done(itr::RegexMatchIterator, prev_match) = (prev_match === nothing) +iteratorsize(::Type{RegexMatchIterator}) = SizeUnknown() # Assumes prev_match is not nothing function next(itr::RegexMatchIterator, prev_match) diff --git a/base/task.jl b/base/task.jl index a0e2422f84d01..095d89b31950a 100644 --- a/base/task.jl +++ b/base/task.jl @@ -253,6 +253,8 @@ function done(t::Task, val) istaskdone(t) end next(t::Task, val) = (t.result, nothing) +iteratorsize(::Type{Task}) = SizeUnknown() +iteratoreltype(::Type{Task}) = EltypeUnknown() isempty(::Task) = error("isempty not defined for Tasks") diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 28d22b31554a4..71d3b36457138 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -385,6 +385,7 @@ type GenericIterator{N} end Base.start{N}(::GenericIterator{N}) = 1 Base.next{N}(::GenericIterator{N}, i) = (i, i + 1) Base.done{N}(::GenericIterator{N}, i) = i > N ? true : false +Base.iteratorsize{N}(::Type{GenericIterator{N}}) = Base.SizeUnknown() function test_map(::Type{TestAbstractArray}) diff --git a/test/simdloop.jl b/test/simdloop.jl index 782c4e91f9cd6..771383aedf419 100644 --- a/test/simdloop.jl +++ b/test/simdloop.jl @@ -104,17 +104,17 @@ end crng = CartesianRange(CartesianIndex{4}(2,0,1,3), CartesianIndex{4}(4,1,1,5)) indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) -@test indexes == collect(crng) +@test indexes == vec(collect(crng)) crng = CartesianRange(CartesianIndex{2}(-1,1), CartesianIndex{2}(1,3)) indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) -@test indexes == collect(crng) +@test indexes == vec(collect(crng)) crng = CartesianRange(CartesianIndex{2}(-1,1), CartesianIndex{2}(-1,3)) indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) -@test indexes == collect(crng) +@test indexes == vec(collect(crng)) crng = CartesianRange(CartesianIndex{1}(2), CartesianIndex{1}(4)) @@ -124,7 +124,7 @@ indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) crng = CartesianRange(CartesianIndex{0}(), CartesianIndex{0}()) indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) -@test indexes == collect(crng) +@test indexes == vec(collect(crng)) # @simd with array as "range" # issue #13869 diff --git a/test/unicode/utf8proc.jl b/test/unicode/utf8proc.jl index 5cca4da65c1b6..4f979c347b721 100644 --- a/test/unicode/utf8proc.jl +++ b/test/unicode/utf8proc.jl @@ -244,7 +244,7 @@ let grphtest = (("b\u0300lahβlahb\u0302láh", ["b\u0300","l","a","h", @test typeof(first(graphemes(s_))) == SubString{typeof(s_)} end grph = collect(graphemes(s_)) - @test isempty(grph) || eltype(grph) == SubString{typeof(s_)} + @test eltype(grph) == SubString{typeof(s_)} @test grph == g_ @test length(graphemes(s_)) == length(grph) end