Skip to content
This repository has been archived by the owner on Sep 1, 2020. It is now read-only.

Commit

Permalink
Merge pull request #74 from JuliaLang/eltype-overhaul
Browse files Browse the repository at this point in the history
Make all eltypes depend only on iterator type
  • Loading branch information
iamed2 authored Sep 23, 2016
2 parents ac6b55b + b4eb5c6 commit 05b67ed
Showing 1 changed file with 36 additions and 47 deletions.
83 changes: 36 additions & 47 deletions src/Iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ immutable TakeStrict{I}
end
iteratorsize{T<:TakeStrict}(::Type{T}) = HasLength()

eltype(it::TakeStrict) = eltype(it.xs)
eltype{I}(::Type{TakeStrict{I}}) = eltype(I)

takestrict(xs, n::Int) = TakeStrict(xs, n)

Expand Down Expand Up @@ -105,23 +105,15 @@ done(it::RepeatCallForever, state) = false

# Concatenate the output of n iterators

immutable Chain
xss::Vector{Any}
function Chain(xss...)
new(Any[xss...])
end
immutable Chain{T<:Tuple}
xss::T
end

iteratorsize{T<:Chain}(::Type{T}) = SizeUnknown()

function eltype(it::Chain)
try
typejoin([eltype(xs) for xs in it.xss]...)
catch
Any
end
end
eltype{T}(::Type{Chain{T}}) = typejoin([eltype(t) for t in T.parameters]...)

chain(xss...) = Chain(xss...)
chain(xss...) = Chain(xss)

function start(it::Chain)
i = 1
Expand Down Expand Up @@ -154,18 +146,16 @@ done(it::Chain, state) = state[1] > length(it.xss)

# Cartesian product as a sequence of tuples

immutable Product
xss::Vector{Any}
function Product(xss...)
new(Any[xss...])
end
immutable Product{T<:Tuple}
xss::T
end

iteratorsize{T<:Product}(::Type{T}) = SizeUnknown()

eltype(p::Product) = Tuple{map(eltype, p.xss)...}
eltype{T}(::Type{Product{T}}) = Tuple{map(eltype, T.parameters)...}
length(p::Product) = mapreduce(length, *, 1, p.xss)

product(xss...) = Product(xss...)
product(xss...) = Product(xss)

function start(it::Product)
n = length(it.xss)
Expand Down Expand Up @@ -216,7 +206,7 @@ immutable Distinct{I}
end
iteratorsize{T<:Distinct}(::Type{T}) = SizeUnknown()

eltype(it::Distinct) = eltype(it.xs)
eltype{I}(::Type{Distinct{I}}) = eltype(I)

distinct{I}(xs::I) = Distinct{I}(xs)

Expand Down Expand Up @@ -251,31 +241,30 @@ done(it::Distinct, state) = done(it.xs, state[1])
# partition(count(1), 2, 1) = (1,2), (2,3), (3,4) ...
# partition(count(1), 2, 3) = (1,2), (4,5), (7,8) ...

immutable Partition{I}
immutable Partition{I, N}
xs::I
n::Int
step::Int
end
iteratorsize{T<:Partition}(::Type{T}) = SizeUnknown()

eltype(it::Partition) = Tuple{fill(eltype(it.xs),it.n)...}
eltype{I, N}(::Type{Partition{I, N}}) = NTuple{N, eltype(I)}

function partition(xs, n::Int)
Partition(xs, n, n)
function partition{I}(xs::I, n::Int)
Partition{I, n}(xs, n)
end

function partition(xs, n::Int, step::Int)
function partition{I}(xs::I, n::Int, step::Int)
if step < 1
throw(ArgumentError("Partition step must be at least 1."))
end

Partition(xs, n, step)
Partition{I, n}(xs, step)
end

function start(it::Partition)
p = Array(eltype(it.xs), it.n)
function start{I, N}(it::Partition{I, N})
p = Vector{eltype(I)}(N)
s = start(it.xs)
for i in 1:(it.n - 1)
for i in 1:(N - 1)
if done(it.xs, s)
break
end
Expand All @@ -284,26 +273,26 @@ function start(it::Partition)
(s, p)
end

function next(it::Partition, state)
function next{I, N}(it::Partition{I, N}, state)
(s, p0) = state
(x, s) = next(it.xs, s)
ans = p0; ans[end] = x

p = similar(p0)
overlap = max(0, it.n - it.step)
overlap = max(0, N - it.step)
for i in 1:overlap
p[i] = ans[it.step + i]
end

# when step > n, skip over some elements
for i in 1:max(0, it.step - it.n)
for i in 1:max(0, it.step - N)
if done(it.xs, s)
break
end
(x, s) = next(it.xs, s)
end

for i in (overlap + 1):(it.n - 1)
for i in (overlap + 1):(N - 1)
if done(it.xs, s)
break
end
Expand All @@ -323,7 +312,7 @@ done(it::Partition, state) = done(it.xs, state[1])
# Inspired by itertools.groupby in python.
# E.g.,
# x = ["face", "foo", "bar", "book", "baz", "zzz"]
# groupby(x, z -> z[1]) =
# groupby(z -> z[1], x) =
# ["face", "foo"]
# ["bar", "book", "baz"]
# ["zzz"]
Expand All @@ -333,8 +322,8 @@ immutable GroupBy{I}
end
iteratorsize{T<:GroupBy}(::Type{T}) = SizeUnknown()

eltype{I}(it::GroupBy{I}) = I
eltype{I<:Range}(it::GroupBy{I}) = Array{eltype(it.xs),}
# eltype{I}(it::GroupBy{I}) = I
eltype{I}(::Type{GroupBy{I}}) = Vector{eltype(I)}

function groupby(xs, keyfunc::Function)
Base.warn_once("groupby(xs, keyfunc) should be groupby(keyfunc, xs)")
Expand All @@ -352,9 +341,9 @@ function start(it::GroupBy)
return (s, (prev_key, prev_value))
end

function next(it::GroupBy, state)
function next{I}(it::GroupBy{I}, state)
(s, (prev_key, prev_value)) = state
values = Array(eltype(it.xs), 0)
values = Vector{eltype(I)}(0)
# We had a left over value from the last time the key changed.
if prev_value != nothing || prev_key != nothing
push!(values, prev_value)
Expand Down Expand Up @@ -415,12 +404,12 @@ end

# Iterate over all subsets of a collection

immutable Subsets
xs
immutable Subsets{C}
xs::C
end
iteratorsize{T<:Subsets}(::Type{T}) = HasLength()

eltype(it::Subsets) = Array{eltype(it.xs),1}
eltype{C}(::Type{Subsets{C}}) = Vector{eltype(C)}
length(it::Subsets) = 1 << length(it.xs)

function subsets(xs)
Expand Down Expand Up @@ -456,13 +445,13 @@ end
# Iterate over all subsets of a collection with a given size

immutable Binomial{T}
xs::Array{T,1}
xs::Vector{T}
n::Int64
k::Int64
end
iteratorsize{T<:Binomial}(::Type{T}) = HasLength()

eltype(it::Binomial) = Array{eltype(it.xs),1}
eltype{T}(::Type{Binomial{T}}) = Vector{T}
length(it::Binomial) = binomial(it.n,it.k)

subsets(xs,k) = Binomial(xs,length(xs),k)
Expand Down Expand Up @@ -538,7 +527,7 @@ function takenth(xs, interval::Integer)
end
TakeNth(xs, convert(UInt, interval))
end
eltype(en::TakeNth) = eltype(en.xs)
eltype{I}(::Type{TakeNth{I}}) = eltype(I)


function start(it::TakeNth)
Expand Down

0 comments on commit 05b67ed

Please sign in to comment.