I was just watching a video by rockthejvm that can be found here. My only issue is that it fails to address if match types can do anything method overloading cannot? Is there anything that match types do better than method overloading? It seems they are just a less extensible version of method overloading.
Any wisdom would be greatly appreciated.
This example from the documentation:
type LeafElem[X] = X match
case String => Char
case Array[t] => LeafElem[t]
case Iterable[t] => LeafElem[t]
case AnyVal => X
def leafElem[X](x: X): LeafElem[X] = x match
case x: String => x.charAt(0)
case x: Array[t] => leafElem(x(9))
case x: Iterable[t] => leafElem(x.head)
case x: AnyVal => x
can't be translated to overloading. The non-recursive cases are easy:
def leafElem(x: String): Char = x.charAt(0)
def leafElem(x: AnyVal): AnyVal = x
but what would you do with arrays? If you write
def leafElem[T](x: Array[T]): ??? = leafElem(x(9))
then:
T
must be the parameter type of a leafElem
overload" required for the body to compile.Or consider this non-recursive example
type Elem[X] = X match
case String => Char
case Array[t] => t
case Iterable[t] => t
def elem[X](x: X): Elem[X] = x match { /* doesn't really matter */ }
With match types you can write
def mapElems[X](seq: Seq[X]): Seq[Elem[X]] = seq.map(elem(_))
If you had overloaded elem
methods for separate cases, mapElems
wouldn't compile (and again you couldn't write its return type if it did).