# Syntax Proposal - Pattern matched functions

I believe this is the correct place to make such a proposal; if I’m wrong, please point me to the proper location.

Problem

It’s common for people to define functions that match entirely on their arguments, especially when working with ADTs:

``````def concat[A](xs: List[A], ys: List[A]): List[A] = (xs, ys) match {
case (Nil, Nil) => Nil
case (Nil, ys) => ys
case (xs, Nil) => xs
case (xs, ys) => xs ++ ys
}
``````

It’s somewhat cumbersome to have to create a tuple just to match on the arguments of the function.

Proposal

Permit the following:

``````def concat[A](xs: List[A], ys: List[A]): List[A] = {
case (Nil, Nil) => Nil
case (Nil, ys) => ys
case (xs, Nil) => xs
case (xs, ys) => xs ++ ys
}
``````

Which is interpreted as the above example.

This also applies to `val` function definitions:

``````val sum = (x: Int, y: Int) => {
case (0, 0) => 0
case (0, y) => y
case (x, 0) => x
case (x, y) => x + y
}
``````

It should be noted that the following syntax already works (in Scala 2.x):

``````val sum: (Int, Int) => Int = {
case (0, 0) => 0
case (0, y) => y
case (x, 0) => x
case (x, y) => x + y
}
``````

Partial Functions

`PartialFunction` currently uses this syntax, albeit, it requires an explicit type-declaration:

``````def concatEmpty[A]: PartialFunction[(List[A], List[A]), List[A]] = {
case (Nil, Nil) => Nil
}
``````

Note: there are no parameters on the above, as a `PartialFunction` takes its parameters when it’s applied.

When a function producing a `PartialFunction` takes parameters, those parameters become part of the PF definition, and not its evaluation:

``````def foo[A](x: Int): PartialFunction[(List[A], List[A]), Int] = {
case (Nil, Nil) => x
}
``````

This means we can prevent a conflict by adding the rule that this syntax re-writing is never done when the result type of a function is a `PartialFunction`.

2 Likes

This would also create an ambiguity for the following code:

``````def foo(x: Int, y: Int): (Int, Int) => Int = {
case (a, b) => ???
}
``````

You wouldn’t know whether it is supposed to mean

``````def foo(x: Int, y: Int): (Int, Int) => Int = { (f, g) =>
(f, g) match {
case (a, b) => ???
}
}
``````

(as it currently does) or

``````def foo(x: Int, y: Int): (Int, Int) => Int = {
(x, y) match {
case (a, b) => ???
}
}
``````

This means we can prevent a conflict by adding the rule that this syntax re-writing is never done when the result type of a function is a `PartialFunction`.

Adding a rule to compensate a conflict created by the addition of new desugaring is a language design smell.

This would also create an ambiguity for the following code:

def foo(x: Int, y: Int): (Int, Int) => Int = {
case (a, b) => ???
}

I hadn’t considered that. Looks like this is a non-starter. Thanks for finding the hole in my reasoning, I thought I had it all figured out!

1 Like