Search code examples
scalaoperator-precedence

Operator precedence in scala behaves strange


I was experimenting with operator precedence in Scala, and there is something strange happening here:

class Op{
  def +(that:Op):Op={println("called +");this}
  def -(that:Op):Op={println("called -");this}
  def *(that:Op):Op={println("called *");this}
  def /(that:Op):Op={println("called /");this}
  def %(that:Op):Op={println("called %");this}
}

val op = new Op;
op+op-op*op/op%op ;
op+op*op ;

For the first line, the output is:

called +
called *
called /
called %
called -

(Notice + is called before *.) However, for the second line, the output is:

called *
called +

(* is called before +.) I believe from what I read here that * should be called before +. Is there something I got wrong?


Solution

  • Scala groups the expression by precedence, then evaluates the groups strictly from left to right, thus adhering to the precedence.

    Your second call is equivalent to

    op.+(op.*(op))
    

    which is evaluated from inside to outside.

    The same with the first call:

    op+op-op*op/op%op
    

    which becomes, with precedence applied,

    op+op-(op*op/op%op)
    

    or

    (op+op).-(op*op/op%op)
    

    or

    // 1     5    2     3     4
    op.+(op).-(op.*(op)./(op).%(op))