Question about precedence of operator ~ (bitwise not)

I see that the precedence of operation is specified here and if i understand correctly the operations higer in the file have higer precedence, so ~ being at the top has higest precedence. Also using Base.operator_precedence I see that

julia> Base.operator_precedence(:~)
1
julia> Base.operator_precedence(:+)
11
julia> Base.operator_precedence(:*)
12
julia> Base.operator_precedence(:^)
15

So this behaves as expected:

julia> :(~3+2)
:(~3 + 2)
julia> :(~3*2)
:(~3 * 2)

Because ~ has higer precedence and its first applied on three, and then the + is applied
but why does it behave like this then?

julia> :(~3^2)
:(~(3 ^ 2))

I would expect :((~x) ^ y) as result

operator_precedence is about binary operators, and larger numbers have higher precedence.

So, when it is treated as a binary operator, ~ has the lowest precedence, the same as assignment =:

julia> Base.operator_precedence(:(=))
1

julia> Base.operator_precedence(:(~))
1

And indeed, you can define ~ as a binary function:

julia> :(a ~ b)
:(a ~ b)

julia> Base.:(~)(a, b) = a + b

julia> 3 ~ 4
7

The reason that it has assignment precedence was mainly intended for domain-specific languages via metaprogramming/macros, since ~ has an “assignment-like” meaning in statistics. In fact, ~ was originally a special “metaprogramming-only” binary operator that expanded into a macro call: Make tilde automatically quote its arguments · Issue #4882 · JuliaLang/julia · GitHub

Unary operator precedence, on the other hand, is handled differently, and unary operators are higher precedence than * but are trickier for ^. See e.g.

… this is something that could be documented better. (clarify Base.operator_precedence docs: this is only for binary operators by stevengj · Pull Request #60087 · JuliaLang/julia · GitHub … other PRs could improve other portions of the documentation of this kind of thing.)

2 Likes