Pre SIP: Demote match keyword to a method


In Scala 3, would it be possible to make match a method that get injected to any type A?

pipe vs match

scala> final class ChainingOps[A](private val self: A) extends AnyVal {
     |   def pipe[B](f: A => B): B = f(self)
     | }
defined class ChainingOps

scala> implicit final def chainingOps[A](a: A): ChainingOps[A] = new ChainingOps(a)
chainingOps: [A](a: A)ChainingOps[A]

scala> "foo".pipe({ case "foo" => 1; case _ => 2 })
res2: Int = 1

scala> "foo" match { case "foo" => 1; case _ => 2 }
res3: Int = 1

In the above, I am assuming that the semantics of the pipe call and the pattern match expression is the same. Internally there’s a magical optimization that turns pattern match into a series of if-else etc, but the meaning is the same as invoking the function.


One less thing for the language.

When chaining, we can use dot-and-paren syntax:

scala> :paste
  .match({ case "foo" => 2; case _ => 3 })
  .match({ case x if x % 2 == 0 => -7 * x; case _ => 4 })

// Exiting paste mode, now interpreting.

res12: Int = 14

Supports total functions.


FYI, a long time ago, match was a method of scala.Any.

removed 2006 from spec.


I proposed this a while ago, although I didn’t really pursue it.


Do you have a link to the proposal? Were there any feedback to it?


I didn’t mean “proposed” in that sense. I suggested it on Gitter. I was told to open an issue on the dotty github repo, but I don’t think I ever did.


From a user perspective I have always wondered why it’s implemented as a keyword instead of a method. So its definitely worth considering to remove this potential source of confusion.


Is there a way that allows for tail recursion elimination in the match method, without special-cases the match method in the compiler (at which point it could just as well be a language construct again)?


I think of it as similar to the concat + method for Strings. The compiler inlines + calls to use StringBuilder etc, but on the surface the syntax looks like a normal infix method call.

match also could look like a method call, but still retain the current inlining behavior.


You could do that, but then, what’s the upside? You claim its one less thing for the language,
but in reality, it’s still part of the language. I can’t consider something that looks like a regular method, but has and needs support in the compiler to support the desired semantics as not part of the language.

And in addition, while it is made to look like a normal method, it has special non obvious features that normal methods do not have, and will do tail call elimination (but only if the function passed to match method is a literal).

I would really like it if scala were powerful enough that match could be a library-level construct rather than a compiler-level construct. But it’s not.


Any methods attributed to Any or AnyRef that are not already part of java.lang.Object have to be compiler special cases, because we cannot add new methods to java.lang.Object.

I’m assuming the purpose of the proposal is not to make the compiler simpler, but just to reduce the number of keywords.


I agree that the .match syntax is nice. But there are some recent developments which require that match is syntax.

Here’s a direct link to the file in this PR. The relevant bit is that it introduces two new forms of match:

rewrite expr match { cases }
implicit match { cases }


It seems the only choice would be whether to allow calling match with dot syntax and to chain matches — even without the new proposals, pattern matching is a core language construct anyway.


This would be interesting, if it was possible to do everything special about a match in user-space.

Looking at it through that lens, what features does the language need to have in general available to user-space to make that possible? Could the proposed additions of rewrite or inline work outside of a match context somehow?

These are all good questions to ask IMO, and if the day ever comes where one could write their own match method that did everything the language one could, then it would make sense to demote it to a method.