From a212076a7627de35981552a9016353d01f7cd6f5 Mon Sep 17 00:00:00 2001 From: mschauer Date: Tue, 7 May 2019 20:23:02 +0200 Subject: [PATCH 1/6] Define shape of truncated zips with `HasShape{1}` components (updated with the help of @martinholters.) --- base/iterators.jl | 9 +++++---- test/iterators.jl | 24 +++++++++++++++++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/base/iterators.jl b/base/iterators.jl index 0b501006ab946..e63a0513796f0 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -314,10 +314,11 @@ function _zip_min_length(is) end end _zip_min_length(is::Tuple{}) = nothing -size(z::Zip) = _promote_shape(map(size, z.is)...) -axes(z::Zip) = _promote_shape(map(axes, z.is)...) -_promote_shape(a, b...) = promote_shape(a, _promote_shape(b...)) -_promote_shape(a) = a +size(z::Zip) = mapreduce(size, _zip_promote_shape, z.is) +axes(z::Zip) = mapreduce(axes, _zip_promote_shape, z.is) +_zip_promote_shape((a,)::Tuple{OneTo}, (b,)::Tuple{OneTo}) = (intersect(a, b),) +_zip_promote_shape((m,)::Tuple{Integer},(n,)::Tuple{Integer}) = (min(m,n),) +_zip_promote_shape(a, b) = promote_shape(a, b) eltype(::Type{Zip{Is}}) where {Is<:Tuple} = _zip_eltype(Is) _zip_eltype(::Type{Is}) where {Is<:Tuple} = tuple_type_cons(eltype(tuple_type_head(Is)), _zip_eltype(tuple_type_tail(Is))) diff --git a/test/iterators.jl b/test/iterators.jl index 53b18284505eb..0bb27da12e229 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -14,10 +14,32 @@ let z = zip(1:2) @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) From 75a934a038e070117f621e1e8c577fc46b57a880 Mon Sep 17 00:00:00 2001 From: mschauer Date: Wed, 8 May 2019 12:56:51 +0200 Subject: [PATCH 2/6] Also test size of zipped 2d-iterators --- test/iterators.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/iterators.jl b/test/iterators.jl index 0bb27da12e229..4bb4a764a4865 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -42,6 +42,15 @@ let z = zip([i*j for i in 1:3, j in -1:2:1], 1:6) @test length(z) == 6 end +let z = zip([i*j for i in 1:3, j in -1:2:1], [i*j for i in 1:3, j in -1:2:1]) + @test collect(z) == [(-1, -1) (1, 1) + (-2, -2) (2, 2) + (-3, -3) (3, 3)] + @test eltype(z) == Tuple{Int,Int} + @test size(z) == (3, 2) + @test length(z) == 6 +end + let z = zip(1:2, 3:4, 5:6) @test size(z) == (2,) @test collect(z) == [(1,3,5), (2,4,6)] From 916678adc63386c10066f62442dd3e3d29bd8ddc Mon Sep 17 00:00:00 2001 From: mschauer Date: Wed, 14 Aug 2019 15:23:06 +0200 Subject: [PATCH 3/6] News item for "Define shape of some truncated zips". --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 0d440d9c8e893..896cb99e3ad81 100644 --- a/NEWS.md +++ b/NEWS.md @@ -92,6 +92,9 @@ Deprecated or removed --------------------- +* A 1-d `Zip` iterator (where `Base.IteratorSize` +is `Base.HasShape{1}()`) with defined length of `n` has now also size of `(n,)` (instead of throwing an error) ([#29927]). + External dependencies --------------------- From 95da620fe927c1825193bb36afb375111befb0af Mon Sep 17 00:00:00 2001 From: mschauer Date: Mon, 2 Dec 2019 11:55:36 +0100 Subject: [PATCH 4/6] Move news item about shape of zips. --- NEWS.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 896cb99e3ad81..c411e0f59a3f4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -52,6 +52,8 @@ Standard library changes * Sets are now displayed less compactly in the REPL, as a column of elements, like vectors and dictionaries ([#33300]). +* A 1-d `Zip` iterator (where `Base.IteratorSize` is `Base.HasShape{1}()`) with defined length of `n` has now also size of `(n,)` (instead of throwing an error) ([#29927]). + #### Libdl #### LinearAlgebra @@ -91,10 +93,6 @@ Standard library changes Deprecated or removed --------------------- - -* A 1-d `Zip` iterator (where `Base.IteratorSize` -is `Base.HasShape{1}()`) with defined length of `n` has now also size of `(n,)` (instead of throwing an error) ([#29927]). - External dependencies --------------------- From 549c402fceee7e6bfba14c194714b622a12e9b8f Mon Sep 17 00:00:00 2001 From: Moritz Schauer Date: Sat, 4 Apr 2020 15:20:18 +0200 Subject: [PATCH 5/6] Textual suggestion from review Co-Authored-By: Rafael Fourquet --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index f0abd50ba5ddd..f0b3bbd0233f4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -28,7 +28,7 @@ New library features Standard library changes ------------------------ -* A 1-d `Zip` iterator (where `Base.IteratorSize` is `Base.HasShape{1}()`) with defined length of `n` has now also size of `(n,)` (instead of throwing an error) ([#29927]). +* A 1-d `Zip` iterator (where `Base.IteratorSize` is `Base.HasShape{1}()`) with defined length of `n` has now also size of `(n,)` (instead of throwing an error with truncated iterators) ([#29927]). * The `@timed` macro now returns a `NamedTuple` ([#34149]) #### LinearAlgebra From 3633a0ab8e4cb9ced33c84e2294b2fad0c6df098 Mon Sep 17 00:00:00 2001 From: Moritz Schauer Date: Sat, 4 Apr 2020 15:30:55 +0200 Subject: [PATCH 6/6] Apply suggestions from code review --- test/iterators.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/iterators.jl b/test/iterators.jl index 059c851f30e4c..c8d8b512fb31d 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -27,6 +27,7 @@ let z = zip(1:2, Iterators.countfrom(3)) @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_throws MethodError axes(z) @test length(z) == 2 end @@ -39,6 +40,7 @@ let z = zip([i*j for i in 1:3, j in -1:2:1], 1:6) (3, 6) ] @test eltype(z) == Tuple{Int,Int} @test_throws DimensionMismatch size(z) + @test_throws DimensionMismatch axes(z) @test length(z) == 6 end @@ -48,6 +50,7 @@ let z = zip([i*j for i in 1:3, j in -1:2:1], [i*j for i in 1:3, j in -1:2:1]) (-3, -3) (3, 3)] @test eltype(z) == Tuple{Int,Int} @test size(z) == (3, 2) + @test axes(z) == (Base.OneTo(3), Base.OneTo(2)) @test length(z) == 6 end