Skip to content

Commit

Permalink
Add default IsScalar trait
Browse files Browse the repository at this point in the history
  • Loading branch information
pabloferz committed Jun 24, 2016
1 parent 45fa65f commit ab15651
Show file tree
Hide file tree
Showing 9 changed files with 36 additions and 10 deletions.
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
6 changes: 6 additions & 0 deletions base/tuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ getindex(t::Tuple, b::AbstractArray{Bool}) = getindex(t,find(b))

## iterating ##

<<<<<<< HEAD
iteratorsize{T<:Tuple}(::Type{T}) = HasLength()
=======
iteratorsize(::Tuple) = HasLength()
>>>>>>> d7ef4cc... Add default IsScalar trait

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

0 comments on commit ab15651

Please sign in to comment.