sirex
1
Here is what I got:
julia> for i in zip(1:3, 2:5)
println(i)
end
(1, 2)
(2, 3)
(3, 4)
julia> [i for i in zip(1:3, 2:5)]
ERROR: DimensionMismatch("dimensions must match")
Why zip
works differently in list comprehension? Is this a feature or a bug?
3 Likes
I’d say this is a bug because
julia> length(zip(1:3, 2:5))
3
julia> eltype(zip(1:3, 2:5))
Tuple{Int64,Int64}
makes pretty clear what collect should do.
sirex
3
piever
4
The problem is that zip(1:3, 1:4)
declares to have a well defined shape but errors when one asks what it is:
julia> itr = zip(1:3, 1:4)
Base.Iterators.Zip2{UnitRange{Int64},UnitRange{Int64}}(1:3, 1:4)
julia> Base.IteratorSize(itr)
Base.HasShape{1}()
julia> size(itr)
ERROR: DimensionMismatch("dimensions must match")
Stacktrace:
[1] promote_shape at ./indices.jl:87 [inlined]
[2] size(::Base.Iterators.Zip2{UnitRange{Int64},UnitRange{Int64}}) at ./iterators.jl:290
[3] top-level scope at none:0
julia> length(itr)
3
Not sure what’s a good fix: the one dimensional case is easy, but the multidimensional case not so much:
collect(zip(rand(2, 3), rand(2, 3)))
For things to be type stable it should return a matrix. However what shape should the matrix have is a bit unclear, so maybe this needs to error.
2 Likes
Liso
5
This could be utterly wrong because I didn’t analyze impact to other areas!!! (and it is just draft!)
julia> import Base.axes
julia> axes(z::Base.Iterators.Zip2) = min(axes(z.a), axes(z.b))
axes (generic function with 29 methods)
julia> [i for i in zip(1:3,2:5)]
3-element Array{Tuple{Int64,Int64},1}:
(1, 2)
(2, 3)
(3, 4)
julia> collect(zip(rand(2, 3), rand(2, 3)))
2×3 Array{Tuple{Float64,Float64},2}:
(0.67172, 0.578706) (0.745477, 0.868811) (0.759369, 0.390175)
(0.786294, 0.0748731) (0.0990557, 0.746172) (0.160871, 0.711756)
I was inspired by:
length(z::Zip2) = _min_length(z.a, z.b, IteratorSize(z.a), IteratorSize(z.b))
which also means that draft above has to check (at least) infinite cases!
1 Like