Truth values, precedence and arithmetic operators

While making a code, I had the following condition to throw an error:

n<0 | !isa(n,Integer)

For n=3.0, the code was giving false. Though it took me a while, I now understand that “|” takes precedence. Even though, in the docs, it says that Julia (unlike Python, but like Java) throws an error when trying to use integers in a local context, but when I do

n<0 | (!isa(n,Integer))

it aparently makes

n<(0|(true))

which gives

n<1

when in doubt, you can always check it:

julia> Meta.@lower n<0 | !isa(n,Integer)
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = <
│   %2 = n
│   %3 = |
│   %4 = !
│   %5 = n isa Integer
│   %6 = (%4)(%5)
│   %7 = (%3)(0, %6)
│   %8 = (%1)(%2, %7)
└──      return %8
))))

so the (%3)(0, %6) is doing `|(0, !(n isa Integer)) first, as you have realized.

the second thing is that | is bitwise or, you probably wanted || for boolean or?

actually if you use ||, the lowering is different (duh

julia> Meta.@lower n<0 || !isa(n,Integer)
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = n < 0
└──      goto #3 if not %1
2 ─      return %1
3 ─ %4 = !
│   %5 = n isa Integer
│   %6 = (%4)(%5)
└──      return %6
))))

because:

julia> Base.operator_precedence(:|)
11

julia> Base.operator_precedence(:||)
5

The point is that | in Julia is bitwise OR, and is treated like an arithmetic operator similar to + (hence having higher precedence than <).

Usually, for logical OR in Julia, people use ||, which has lower precedence than < and is probably what you want here.

(The caveat is that || is short-circuiting. Very occasionally, for performance-critical code in a tight loop, it is sometimes faster to use the non-short-circuiting |. But in this case you usually need explicit parentheses to make the precedence come out right.)

1 Like