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
.