0

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?

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
  • @puhlen there is nothing strange or buggy, calls are grouped by precedence and then evaluated from left to right, as expected, see the end of my answer. – 0__ Jun 09 '17 at 17:58

1 Answers1

4

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))
0__
  • 66,707
  • 21
  • 171
  • 266
  • Read the question, this is not what op is asking about. op + op - op * op produces `+ * -` as it compiles to `op.+(op).-(op*(op))` – puhlen Jun 09 '17 at 17:48
  • I understood the op to ask this – Adrian Jun 09 '17 at 17:50
  • @puhlen what do you mean by "the entire expression"? I don't see any other way to sequence this. Scala does not assume commutativity, so it correctly refrains from evaluating the steps (2, 3, 4) before step 1, but sticks to strict left-to-right where applicable. – 0__ Jun 09 '17 at 18:02
  • Yeah, I was confused, this is how it should be. – puhlen Jun 09 '17 at 18:04