Search code examples
scalascala-collectionsobject-notation

Why does object notation in Scala apparently eliminate the right side associativity of methods ending in ':'?


I am currently getting into Scala and am wondering about the difference it makes to use object notation when calling methods ending with ':'. As a method name ending in ':' would normally produce right-side associativity, this seems to change when invocating such a method with object notation.

Example:

scala> 3 +: List(1,2) 
res1: List[Int] = List(3, 1, 2) 

scala> List(1,2) +: 3 // does not compile due to right side associativity

scala> (List(1,2)).+:(3) 
res2: List[Int] = List( 3, 1, 2)

Now I do not understand why the right-associativity feature gets disabled by using object notation. Could someone explain this or link to the documentation on this issue?


Solution

  • From the spec, "Infix Operations":

    The associativity of an operator is determined by the operator's last character. Operators ending in a colon `:' are right-associative. All other operators are left-associative.

    Method +: is defined on the List, which is why (List(1,2)).+:(3) works. Its implementation is such that the element is put in the front, so equivalent to 3 :: List(1, 2), but that's irrelevant here.

    Using infix notation List(1,2) +: 3 won't work, because (as stated in the spec) all infix operators ending with a colon are right-associative, which means that the "right hand side" is using the operator with "left hand side" as a parameter, instead of vice-versa.

    Basically,

    1 +: 2 +: 3 +: List(4, 5) 
    

    and

    List(4, 5).+:(3).+:(2).+:(1)
    

    have identical effect (I know that has been pretty much obvious in your question already, but I'm just emphasizing the right-associativity).

    So, to answer your question in one simple sentence: it's not that right-side associativity is removed in object notation, it's more that it's added in the infix notation, but only for methods ending with a colon.