Boolean array in comprehensions

I am trying to understand Julia comprehensions and their filter systems (in version 1.0):

julia> aa = [2,2,1,2]
4-element Array{Int64,1}:
 2
 2
 1
 2
bb = [1,1,1,0]
4-element Array{Int64,1}:
 1
 1
 1
 0
julia> [i for i=1:4 if aa[i] == bb[i] ] #works as expected, returns only the third element
1-element Array{Int64,1}:
 3

However, using the .== command does not work:

julia> [i for i=1:4 if aa .== bb ]
ERROR: TypeError: non-boolean (BitArray{1}) used in boolean context
Stacktrace:
 [1] iterate at ./iterators.jl:434 [inlined]
 [2] iterate at ./generator.jl:44 [inlined]
 [3] grow_to!(::Array{Int64,1}, ::Base.Generator{Base.Iterators.Filter{getfield(Main, Symbol("##36#38")),UnitRange{Int64}},getfield(Main, Symbol("##35#37"))}) at ./array.jl:674
 [4] collect(::Base.Generator{Base.Iterators.Filter{getfield(Main, Symbol("##36#38")),UnitRange{Int64}},getfield(Main, Symbol("##35#37"))}) at ./array.jl:617
 [5] top-level scope at none:0
#although the .== commands works by itself:
julia> aa .== bb
4-element BitArray{1}:
 false
 false
  true
 false

Can someone please explain this behaviour? In the documentation it says:

In Julia, if A and B are arrays, logical comparison operations like A == B do not return an array of booleans. Instead, use A .== B, and similarly for the other boolean operators like <, > and =.

The if clause of a filtered comprehension is executed on every iteration of the for clause, and it needs to return a single true or false that determines if that specific iteration should be filtered from the output.

Using .== is not what you want on two counts: It doesn’t return a single true/false value, and it’ll be slower because it’s computing all values across the entire arrays on every single iteration!

Remember that Julia is fast at working element-wise across collections — there’s no need to bend over backwards trying to vectorize things.

4 Likes