Strange behavior for subtraction AST?

Hi, I was wondering why the Julia AST automatically splits subtraction into multiple operations:

julia> :(x-y-z)
:((x - y) - z)

julia> dump(ans)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol -
    2: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol -
        2: Symbol x
        3: Symbol y
      typ: Any
    3: Symbol z
  typ: Any

versus

julia> :(-(x,y,z))
:(-(x, y, z))

julia> dump(ans)
Expr
  head: Symbol call
  args: Array{Any}((4,))
    1: Symbol -
    2: Symbol x
    3: Symbol y
    4: Symbol z
  typ: Any

I would have thought that the second AST is simpler and more efficient code, but maybe it really doesn’t matter because the compiler optimizes it already. But I was wondering why the default behavior is to introduce an extra operation into the AST, could someone explain the reason behind that?

julia> :(x+y+z) |> dump
Expr
  head: Symbol call
  args: Array{Any}((4,))
    1: Symbol +
    2: Symbol x
    3: Symbol y
    4: Symbol z
  typ: Any

for +() no extra operations get added into the AST automatically, but it does happen for -().

I have come up with an algorithm that rewrites the AST in the simpler form, but I don’t know if it is a good idea to rewrite it, since the default behavior of splitting the operation might be there for a reason.

1 Like

This is how parsing operators normally works. The real question is why + doesn’t. The answer is that * and + (and IIRC ++) are handled specially while all other operators are parsed in the standard binary left or right associative fashion.

2 Likes