# Difficulties with vectorized logical operations due to operator precedence

I run into this problem all the time. Here’s an example where the vector `x` contains two kinds of missing, the `missing` singleton and a sentinel value of `99`.

``````julia> x = [1, 99, missing, 99, 2, missing, 1];

julia> xmissing1 = ismissing.(x) .| x .== 99
7-element BitArray{1}:
0
1
0
1
0
0
0

julia> xmissing2 = ismissing.(x) .| (x .== 99)
7-element BitArray{1}:
0
1
1
1
0
1
0

julia> xmissing1 == xmissing2
false
``````

The problem here is that `|` has a higher precedence than `==`, which I find unexpected. In my experience, it seems that in other languages comparisons have a higher precedence than logical conjunctions. For example, here is the precedence table for R.

Of course, in Julia, comparisons do have a higher precedence than `&&` and `||`, but those are not broadcastable.

Does anyone else get bit by this behavior? Does the higher precedence of `|` and `&` have anything to do with making vectorized chained comparisons work?

When you write `a = 3 | 4` you expect `a` to be `3`? That’s at least not what I would expect.

1 Like

Yes, frequently. I really want to add dot support to `.&&` and `.||` at some point, but it requires front-end lisp hackery that I’ve not had a chance to do.

2 Likes

Um, not sure I follow you. My example used `==`, not `=`. Assignment does have lower precedence than comparison operators, as expected.

To clarify, I never use `|` and `&` as bitwise operators on numbers, I only use them for vectorized boolean operations. So I have no expectation regarding what `3 | 4` should equal.

Would the vectorized `&&` and `||` use three-value logic? Because of course right now the scalar versions do not:

``````julia> missing || true
ERROR: TypeError: non-boolean (Missing) used in boolean context
Stacktrace:
 top-level scope at REPL:1
``````

No, I would want and expect them to behave exactly like their scalar counterparts.

You are right, however, that this would appear quite frequently with missing data.

Hmmm, well then I’m afraid I wouldn’t be able to use `.||` and `.&&` very often. E.g., in the above example, `x .== 99` contains `missing`s, so I would still have to use `.|`.

Until then, one can do something like

``````(x -> ismissing(x) || x == 99).(x)
``````
1 Like