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

Length fixes (#100 and a fix for 0.6) #101

Merged
merged 2 commits into from
Apr 7, 2017
Merged
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
42 changes: 27 additions & 15 deletions src/Iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,17 @@ if VERSION < v"0.5.0-dev+3305"
function iteratorsize(v)
error("Do not call this on older versions")
end

has_length(it) = applicable(length, it)
else
import Base: iteratorsize, SizeUnknown, IsInfinite,
HasLength, HasShape

function has_length(it)
it_size = iteratorsize(it)

return isa(it_size, HasLength) || isa(it_size, HasShape)
end
end


Expand Down Expand Up @@ -116,20 +124,7 @@ immutable Chain{T<:Tuple}
xss::T
end

if VERSION >= v"0.5.0-dev+3305"
iteratorsize{T}(::Type{Chain{T}}) = _chain_is(T)

@generated function _chain_is{T}(t::Type{T})
for itype in T.types
if iteratorsize(itype) == IsInfinite()
return :(IsInfinite())
elseif iteratorsize(itype) == SizeUnknown()
return :(SizeUnknown())
end
end
return :(HasLength())
end
end
# iteratorsize method defined at bottom because of how @generated functions work in 0.6 now

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

Expand Down Expand Up @@ -518,7 +513,7 @@ done(it::Binomial, state::BinomialIterState) = state.done
function nth(xs, n::Integer)
n > 0 || throw(BoundsError(xs, n))
# catch, if possible
applicable(length, xs) && (n ≤ length(xs) || throw(BoundsError(xs, n)))
has_length(xs) && (n ≤ length(xs) || throw(BoundsError(xs, n)))
s = start(xs)
i = 0
while !done(xs, s)
Expand Down Expand Up @@ -853,4 +848,21 @@ macro chain(ex)
Expr(:let, Expr(:block, cycleex...), states...)
end

if VERSION >= v"0.5.0-dev+3305"
iteratorsize{T}(::Type{Chain{T}}) = _chain_is(T)

# on 0.6, must be defined after the other iteratorsize methods are defined
# generated functions probably should not be used going forward
@generated function _chain_is{T}(t::Type{T})
for itype in T.types
if iteratorsize(itype) == IsInfinite()
return :(IsInfinite())
elseif iteratorsize(itype) == SizeUnknown()
return :(SizeUnknown())
end
end
return :(HasLength())
end
end

end # module Iterators
3 changes: 3 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,9 @@ s = subsets([1, 2, 3])
@test_throws BoundsError nth(s, 0)
@test_throws BoundsError nth(s, length(s) + 1)

# #100
nth(drop(repeatedly(() -> 1), 1), 1)


# Every nth
# ---------
Expand Down