Possible bug in broadcasting operation on array of tuples

broadcast
tuple

#1

Hi all,

I just encountered the following behaviour in v0.6 on Ubuntu:

julia> (1,1) .!= [(1,1), (2,1)]
2-element BitArray{1}:
 true
 true

but if I add one more element to the RHS vector I get an error:

julia> (1,1) .!= [(1,1), (2,1), (1,1)]
ERROR: DimensionMismatch("arrays could not be broadcast to a common size")
Stacktrace:
 [1] _bcs1(::Base.OneTo{Int64}, ::Base.OneTo{Int64}) at ./broadcast.jl:70
 [2] _bcs at ./broadcast.jl:63 [inlined]
 [3] broadcast_shape at ./broadcast.jl:57 [inlined] (repeats 2 times)
 [4] broadcast_indices at ./broadcast.jl:53 [inlined]
 [5] broadcast_c at ./broadcast.jl:311 [inlined]
 [6] broadcast(::Function, ::Tuple{Int64,Int64}, ::Array{Tuple{Int64,Int64},1}) at ./broadcast.jl:434

Note, you can get around this by making the LHS an array too, ie:

julia> [(1,1)] .!= [(1,1), (2,1), (1,1)]
3-element BitArray{1}:
 false
  true
 false

It feels like a bug to me, but I’ve been completely wrong about this sort of stuff before, so I thought I’d ask here before filing an issue.

Cheers,

Colin


#2

The problem is that tuples themselves broadcast:

julia> (1,2) .+ (3,4)
(4, 6)

See ?broadcast for protecting arguments, eg

julia> Ref((1,1)) .!= [(1,1), (2,1), (1,1)]
3-element BitArray{1}:
 false
  true
 false

#3

I think you will understand the behaviour when you read the ?broadcast REPL documentation and possibly check the code at base/broadcast.jl.

You can try this:

julia> (1,1) .!= [(1,1)]
2-element BitArray{1}:
 true
 true

As you can see, this behaviour is different from what you are expecting. Tuple is not treated as a single element in broadcast, and hence, you see a call in base/broadcast.jl (broadcast_indices) to Base.OneTo(length(A)) for ::Type{Tuple}. The above example broadcasts the operation as in:

[1 != (1,1);
 1 != (1,1)]

You can check the below to persuade yourself:

julia> (1,1) .!= [(1,1),1]
2-element BitArray{1}:
  true
 false

Please also note the sentence in ?broadcast:

In this context, anything that is not a subtype of AbstractArray, Ref (except for Ptrs), Tuple, or
  Nullable is considered a scalar.

#4

Ah, I get it. Thanks for the explanation. This is why I asked here instead of filing an issue :slight_smile:

Cheers,

Colin


#5

Thanks, this was a helpful addition to the other responder. I understand how it works now.

Cheers,

Colin


#6

Actually I hadn’t even noticed @Tamas_Papp’s response while writing mine. Sorry for double posting. I am glad that mine also added to the clarity, though.