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.
Ref. https://github.com/JuliaLang/julia/issues/5187#issuecomment-327905053
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:
[1] top-level scope at REPL[56]: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