Skip to content

Commit

Permalink
Define shape of truncated zips with HasShape{1} components.
Browse files Browse the repository at this point in the history
  • Loading branch information
mschauer committed Nov 4, 2018
1 parent e9d32a6 commit a240d19
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 9 deletions.
18 changes: 11 additions & 7 deletions base/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,17 @@ get(f::Base.Callable, v::Pairs, key) = get(f, v.data, key)

abstract type AbstractZipIterator end

_zip_shape((a,)::Tuple{OneTo}, (b,)::Tuple{OneTo}) = (intersect(a, b),)
_zip_shape((m,)::Tuple{Int}, (n,)::Tuple{Int}) = (min(m, n),)
_zip_shape(a, b) = promote_shape(a, b)


zip_iteratorsize(a, b) = and_iteratorsize(a,b) # as `and_iteratorsize` but inherit `Union{HasLength,IsInfinite}` of the shorter iterator
zip_iteratorsize(::HasLength, ::IsInfinite) = HasLength()
zip_iteratorsize(::HasShape, ::IsInfinite) = HasLength()
zip_iteratorsize(a::IsInfinite, b) = zip_iteratorsize(b,a)
zip_iteratorsize(a::IsInfinite, b) = zip_iteratorsize(b, a)
zip_iteratorsize(a::IsInfinite, b::IsInfinite) = IsInfinite()


struct Zip1{I} <: AbstractZipIterator
a::I
end
Expand All @@ -287,8 +291,8 @@ struct Zip2{I1, I2} <: AbstractZipIterator
end
zip(a, b) = Zip2(a, b)
length(z::Zip2) = _min_length(z.a, z.b, IteratorSize(z.a), IteratorSize(z.b))
size(z::Zip2) = promote_shape(size(z.a), size(z.b))
axes(z::Zip2) = promote_shape(axes(z.a), axes(z.b))
size(z::Zip2) = _zip_shape(size(z.a), size(z.b))
axes(z::Zip2) = _zip_shape(axes(z.a), axes(z.b))
eltype(::Type{Zip2{I1,I2}}) where {I1,I2} = Tuple{eltype(I1), eltype(I2)}
@inline isdone(z::Zip2) = isdone(z.a) | isdone(z.b)
@inline isdone(z::Zip2, (sa, sb)::Tuple{Any, Any}) = isdone(z.a, sa) | isdone(z.b, sb)
Expand Down Expand Up @@ -340,7 +344,7 @@ end
zip(iters...)
For a set of iterable objects, return an iterable of tuples, where the `i`th tuple contains
the `i`th component of each input iterable.
the `i`th component of each input iterable. Truncates to the length of the shortest argument.
# Examples
```jldoctest
Expand All @@ -367,8 +371,8 @@ julia> first(c)
"""
zip(a, b, c...) = Zip(a, zip(b, c...))
length(z::Zip) = _min_length(z.a, z.z, IteratorSize(z.a), IteratorSize(z.z))
size(z::Zip) = promote_shape(size(z.a), size(z.z))
axes(z::Zip) = promote_shape(axes(z.a), axes(z.z))
size(z::Zip) = _zip_shape(size(z.a), size(z.z))
axes(z::Zip) = _zip_shape(axes(z.a), axes(z.z))
eltype(::Type{Zip{I,Z}}) where {I,Z} = tuple_type_cons(eltype(I), eltype(Z))
@inline isdone(z::Zip) = isdone(z.a) | isdone(z.z)
@inline isdone(z::Zip, (sa, sz)) = isdone(z.a, sa) | isdone(z.a, sz)
Expand Down
25 changes: 23 additions & 2 deletions test/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,39 @@ using Random
# zip and filter iterators
# issue #4718
@test collect(Iterators.filter(x->x[1], zip([true, false, true, false],"abcd"))) == [(true,'a'),(true,'c')]

let z = zip(1:2)
@test collect(z) == [(1,), (2,)]
# Issue #13979
@test eltype(z) == Tuple{Int}
end

let z = zip(1:2, 3:4)
for z in (zip(1:2, 3:4), zip(1:2, 3:5))
@test collect(z) == [(1,3), (2,4)]
@test eltype(z) == Tuple{Int,Int}
@test size(z) == (2,)
@test axes(z) == (Base.OneTo(2),)
@test length(z) == 2
end

let z = zip(1:2, Iterators.countfrom(3))
@test collect(z) == [(1,3), (2,4)]
@test eltype(z) == Tuple{Int,Int}
@test_throws MethodError size(z) # by convention, the zip of a finite and
# an infinite iterator has only `length`
@test length(z) == 2
end

let z = zip([i*j for i in 1:3, j in -1:2:1], 1:6)
@test collect(z) == [(-1, 1)
(-2, 2)
(-3, 3)
(1, 4)
(2, 5)
(3, 6) ]
@test eltype(z) == Tuple{Int,Int}
@test_throws DimensionMismatch size(z)
@test length(z) == 6
end
let z = zip(1:2, 3:4, 5:6)
@test collect(z) == [(1,3,5), (2,4,6)]
@test eltype(z) == Tuple{Int,Int,Int}
Expand Down

0 comments on commit a240d19

Please sign in to comment.