Search code examples
scalacompiler-errorsoperator-precedenceassociative

error: left- and right-associative operators with same precedence may not be mixed


I'm trying to make a URI DSL in Scala, but infix methods are really giving me trouble.

Even after committing the lengthy and very unintuitive precedence rules to memory, they are still giving me trouble.

class Foo {
  def `://`(a: Unit) = this
  def `:`(b: Unit) = this
}

object Foo {
  def main(args: Array[String]): Unit = {
    new Foo `://` {} `:` {}
  }
}

yields

left- and right-associative operators with same precedence may not be mixed
    new Foo `://` {} `:` {}

                ^

What does this mean? I thought all operators were left-associative.

Is there any way for me to write a DSL that looks like this?

"https" `://` "example.com" `:` 80

Solution

  • From The Scala Language Specification, section 6.12.3:

    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

    The compiler doesn't know whether to interpret your code as this:

    80.`:`("https".`://`("example.com"))
    

    or this:

    "https".`://`(80.`:`("example.com"))
    

    I don't think there's a way to prevent ':' from being treated as a right-associative operator. You could help the compiler out by using parentheses; otherwise, you have to change your operator names.