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

WIP: Add default IsScalar trait #17053

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 9 additions & 0 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ promote_rule{T,n,S}(::Type{Array{T,n}}, ::Type{Array{S,n}}) = Array{promote_type

# make a collection similar to `c` and appropriate for collecting `itr`
_similar_for(c::AbstractArray, T, itr, ::SizeUnknown) = similar(c, T, 0)
_similar_for(c::AbstractArray, T, itr, ::IsScalar) = similar(c, T, ())
_similar_for(c::AbstractArray, T, itr, ::HasLength) = similar(c, T, Int(length(itr)::Integer))
_similar_for(c::AbstractArray, T, itr, ::HasShape) = similar(c, T, convert(Dims,size(itr)))
_similar_for(c, T, itr, isz) = similar(c, T)
Expand All @@ -217,6 +218,8 @@ Return an array of type `Array{element_type,1}` of all items in a collection.
"""
collect{T}(::Type{T}, itr) = collect(Generator(T, itr))

_collect{T}(::Type{T}, itr, ::IsScalar) = (a = Array{T}(); a[] = itr; a)

"""
collect(collection)
Expand All @@ -226,6 +229,12 @@ collect(itr) = _collect(1:1 #= Array =#, itr, iteratoreltype(itr), iteratorsize(

collect_similar(cont, itr) = _collect(cont, itr, iteratoreltype(itr), iteratorsize(itr))

function _collect(cont, itr, ::IteratorEltype, isz::IsScalar)
a = _similar_for(cont, typeof(itr), itr, isz)
a[start(eachindex(a))] = itr
return a
end

_collect(cont, itr, ::HasEltype, isz::Union{HasLength,HasShape}) =
copy!(_similar_for(cont, eltype(itr), itr, isz), itr)

Expand Down
2 changes: 2 additions & 0 deletions base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ _tt1{A,B}(::Type{Pair{A,B}}) = A
_tt2{A,B}(::Type{Pair{A,B}}) = B
eltype{D}(::Type{KeyIterator{D}}) = _tt1(eltype(D))
eltype{D}(::Type{ValueIterator{D}}) = _tt2(eltype(D))
iteratorsize{T<:Union{KeyIterator,ValueIterator}}(::Type{T}) = HasLength()

start(v::Union{KeyIterator,ValueIterator}) = start(v.dict)
done(v::Union{KeyIterator,ValueIterator}, state) = done(v.dict, state)
Expand Down Expand Up @@ -272,6 +273,7 @@ function filter(f, d::Associative)
end

eltype{K,V}(::Type{Associative{K,V}}) = Pair{K,V}
iteratorsize{T<:Union{Associative,AbstractSet}}(::Type{T}) = HasLength()

function isequal(l::Associative, r::Associative)
l === r && return true
Expand Down
1 change: 1 addition & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ done(v::SimpleVector,i) = (i > v.length)
isempty(v::SimpleVector) = (v.length == 0)
indices(v::SimpleVector, d) = d == 1 ? (1:length(v)) : (1:1)
linearindices(v::SimpleVector) = indices(v, 1)
iteratorsize(::Type{SimpleVector}) = HasLength()

function ==(v1::SimpleVector, v2::SimpleVector)
length(v1)==length(v2) || return false
Expand Down
5 changes: 4 additions & 1 deletion base/generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,19 @@ end

abstract IteratorSize
immutable SizeUnknown <: IteratorSize end
immutable IsScalar <: IteratorSize end
immutable HasLength <: IteratorSize end
immutable HasShape <: IteratorSize end
immutable IsInfinite <: IteratorSize end

iteratorsize(x) = iteratorsize(typeof(x))
iteratorsize(::Type) = HasLength() # HasLength is the default
iteratorsize(::Type) = IsScalar() # IsScalar is the default

and_iteratorsize{T}(isz::T, ::T) = isz
and_iteratorsize(::HasLength, ::HasShape) = HasLength()
and_iteratorsize(::HasShape, ::HasLength) = HasLength()
and_iteratorsize(::IsScalar, ::Union{HasLength,HasShape}) = IsScalar()
and_iteratorsize(::Union{HasLength,HasShape}, ::IsScalar) = IsScalar()
and_iteratorsize(a, b) = SizeUnknown()

abstract IteratorEltype
Expand Down
17 changes: 9 additions & 8 deletions base/iterator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ iteratoreltype{I}(::Type{Enumerate{I}}) = iteratoreltype(I)
abstract AbstractZipIterator

zip_iteratorsize(a, b) = and_iteratorsize(a,b) # as `and_iteratorsize` but inherit `Union{HasLength,IsInfinite}` of the shorter iterator
zip_iteratorsize(::IsScalar, ::IsInfinite) = HasLength()
zip_iteratorsize(::HasLength, ::IsInfinite) = HasLength()
zip_iteratorsize(::HasShape, ::IsInfinite) = HasLength()
zip_iteratorsize(a::IsInfinite, b) = zip_iteratorsize(b,a)
Expand Down Expand Up @@ -308,20 +309,16 @@ iteratoreltype{O}(::Type{Repeated{O}}) = HasEltype()
abstract AbstractProdIterator

length(p::AbstractProdIterator) = prod(size(p))
size(p::AbstractProdIterator) = _prod_size(p.a, p.b, iteratorsize(p.a), iteratorsize(p.b))
size(p::AbstractProdIterator) = _prod_size(p.a, p.b)
ndims(p::AbstractProdIterator) = length(size(p))

# generic methods to handle size of Prod* types
_prod_size(a, ::IsScalar) = (1,)
_prod_size(a, ::HasShape) = size(a)
_prod_size(a, ::HasLength) = (length(a), )
_prod_size(a, A) =
_prod_size(a, ::IteratorSize) =
throw(ArgumentError("Cannot compute size for object of type $(typeof(a))"))
_prod_size(a, b, ::HasLength, ::HasLength) = (length(a), length(b))
_prod_size(a, b, ::HasLength, ::HasShape) = (length(a), size(b)...)
_prod_size(a, b, ::HasShape, ::HasLength) = (size(a)..., length(b))
_prod_size(a, b, ::HasShape, ::HasShape) = (size(a)..., size(b)...)
_prod_size(a, b, A, B) =
throw(ArgumentError("Cannot construct size for objects of types $(typeof(a)) and $(typeof(b))"))
_prod_size(a, b) = (_prod_size(a, iteratorsize(a))..., _prod_size(b, iteratorsize(b))...)

# one iterator
immutable Prod1{I} <: AbstractProdIterator
Expand Down Expand Up @@ -413,6 +410,9 @@ iteratorsize{I1,I2}(::Type{Prod{I1,I2}}) = prod_iteratorsize(iteratorsize(I1),it
((x[1][1],x[1][2]...), x[2])
end

prod_iteratorsize(::IsScalar, ::IsScalar) = IsScalar()
prod_iteratorsize(::IsScalar, isz::Union{HasLength,HasShape}) = isz
prod_iteratorsize(isz::Union{HasLength,HasShape}, ::IsScalar) = isz
prod_iteratorsize(::Union{HasLength,HasShape}, ::Union{HasLength,HasShape}) = HasShape()
# products can have an infinite iterator
prod_iteratorsize(::IsInfinite, ::IsInfinite) = IsInfinite()
Expand Down Expand Up @@ -534,6 +534,7 @@ type PartitionIterator{T}
end

eltype{T}(::Type{PartitionIterator{T}}) = Vector{eltype(T)}
iteratorsize{T<:PartitionIterator}(::Type{T}) = HasLength()

function length(itr::PartitionIterator)
l = length(itr.c)
Expand Down
1 change: 1 addition & 0 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ isempty(m::MethodList) = isempty(m.ms)
start(m::MethodList) = start(m.ms)
done(m::MethodList, s) = done(m.ms, s)
next(m::MethodList, s) = next(m.ms, s)
iteratorsize(::Type{MethodList}) = HasLength()

function MethodList(mt::MethodTable)
ms = Method[]
Expand Down
2 changes: 2 additions & 0 deletions base/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## core string functions ##

iteratorsize{T<:AbstractString}(::Type{T}) = HasLength()

endof(s::AbstractString) = error("you must implement endof(", typeof(s), ")")
next(s::AbstractString, i::Int) = error("you must implement next(", typeof(s), ",Int)")
next(s::DirectIndexString, i::Int) = (s[i],i+1)
Expand Down
3 changes: 2 additions & 1 deletion base/strings/utf8proc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Various Unicode functionality from the utf8proc library
module UTF8proc

import Base: show, ==, hash, string, Symbol, isless, length, eltype, start, next, done, convert, isvalid, lowercase, uppercase
import Base: show, ==, hash, string, Symbol, isless, length, eltype, iteratorsize, start, next, done, convert, isvalid, lowercase, uppercase

export isgraphemebreak

Expand Down Expand Up @@ -190,6 +190,7 @@ end
graphemes(s::AbstractString) = GraphemeIterator{typeof(s)}(s)

eltype{S}(::Type{GraphemeIterator{S}}) = SubString{S}
iteratorsize{T<:GraphemeIterator}(::Type{T}) = Base.HasLength()

function length(g::GraphemeIterator)
c0 = Char(0x00ad) # soft hyphen (grapheme break always allowed after this)
Expand Down
2 changes: 2 additions & 0 deletions base/tuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ getindex(t::Tuple, b::AbstractArray{Bool}) = getindex(t,find(b))

## iterating ##

iteratorsize{T<:Tuple}(::Type{T}) = HasLength()

start(t::Tuple) = 1
done(t::Tuple, i::Int) = (length(t) < i)
next(t::Tuple, i::Int) = (t[i], i+1)
Expand Down