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