Search code examples
scalapattern-matchinginfix-operator

What's the associative rule of infix operator in Scala pattern match


I can't organize properly to describe the real question it is. But those examples I think it's enough:
There are some definition class and object here,

  case class ?(a: String, b: Int)
  case class MatchA(a: String, b: Int)

  object MatchInt {// can't
    def unapply(arg: Int): Option[(Long, Double)] = {
      Some(arg, arg)
    }
  }
  object & {// or :? or ?: or +& or +
    def unapply(arg: Int): Option[(Long, Double)] = {
      Some(arg, arg)
    }
  }

Example1, the normal usage of infix extract with a brackets at (b MatchInt c):

  @Test
  def matchOK1(): Unit = {
    MatchA("abc", 123) match {
      case a MatchA (b MatchInt c) =>
        println(s"$a, $b, $c")
    }

  }

Example2, no brackets in b and c but need a special extractor name definition with & or :? or ?: or +& or +, maybe others.

  @Test
  def matchOK2(): Unit = {
    MatchA("abc", 123) match {
      case a MatchA b & c =>
        println(s"$a, $b, $c")
    }
  }

Example3, fail example

  @Test
  def matchFail1(): Unit = {
    MatchA("abc", 123) match {
      case a MatchA b MatchInt c =>
        println(s"$a, $b, $c")
    }

  }

two error occurred:

pattern type is incompatible with expected type;
[error]  found   : Int
[error]  required: Match.this.MatchA
[error]       case a MatchA b MatchInt c =>
[error]                       ^

and

constructor cannot be instantiated to expected type;
[error]  found   : Match.this.MatchA
[error]  required: Long
[error]       case a MatchA b MatchInt c =>
[error]              ^
[error] two errors found

Besides, the error message is very confusing.

Example4, error message similar as former

 @Test
  def matchFail2(): Unit = {
    ?("abc", 123) match {
      case a ? b & c =>
        println(s"$a, $b, $c")
    }

  }

Is there are special rules under the name of extractor that could effect the pattern match?
Thanks a lot.


Solution

  • The pattern expression is parsed just the same as a normal expression.

    (Outside a pattern, you get apply, inside a pattern, you get unapply.)

    The rules for associativity and precedence are in the spec.

    Operators are higher precedence than alnum identifiers.

    That's why your example 2 works, but I guess you don't like that syntax.