Pre SIP: Demote match keyword to a method

Coming back to this… In Scala 3, match is special since it can also be used in match types. So I believe it should still be a keyword. However, we might change the syntax rules for match so that it behaves like a left-associative infix operator with the same precedence as other alpha-numeric operators. That would make using match more flexible. In particular, we could chain matches:

a match 
  case P1 => b
  case P2 => c
match 
  case P3 => d
  case P4 => e

Another variant would be to also allow match to be used after dot. So match would behave like a normal method, except that it is a reserved word. That would help with embedding matches in long chains of conditions. Here’s an example, lifted from real code (the exhaustivity checker in our compiler):

  def canDecompose(tp: Type): Boolean =
    val cls = tp.classSymbol
    cls.is(Sealed)
    && cls.isOneOf(AbstractOrTrait)
    && !cls.hasAnonymousChild
    && cls.children.nonEmpty
    || tp.dealias.match
          case _: OrType => true
          case and: AndType => canDecompose(and.tp1) || canDecompose(and.tp2)
          case _ => false
    || tp.isRef(defn.BooleanClass)
    || tp.isRef(defn.UnitClass)
    || cls.isAllOf(JavaEnumTrait)

That’s actually quite readable taking into account how complex a condition it is. Compare with the original that uses old Scala 2 syntax:

  def canDecompose(tp: Type): Boolean = {
    val dealiasedTp = tp.dealias
    (tp.classSymbol.is(Sealed) &&
      tp.classSymbol.isOneOf(AbstractOrTrait) &&
      !tp.classSymbol.hasAnonymousChild &&
      tp.classSymbol.children.nonEmpty ) ||
    dealiasedTp.isInstanceOf[OrType] ||
    (dealiasedTp.isInstanceOf[AndType] && {
      val and = dealiasedTp.asInstanceOf[AndType]
      canDecompose(and.tp1) || canDecompose(and.tp2)
    }) ||
    tp.isRef(defn.BooleanClass) ||
    tp.isRef(defn.UnitClass) ||
    tp.classSymbol.isAllOf(JavaEnumTrait)
  }
8 Likes