samthebest 的回答可能是真正的原因(我不知道,这不是我所熟悉的),但还有另一种看待它的方式更普遍地与函数式编程相关。
众所周知,函数式编程中的匹配可以在没有任何特殊语言特性的情况下完成(Church Encoding)
trait List[+T] {
def mmatch[R](nil: => R, cons: (T, List[T]) => R): R
}
object Nil extends List[Nothing] {
def mmatch[R](nil: => R, cons: (Nothing, List[Nothing]) => R) = nil
}
class Cons[+T](head: T, tail: List[T]) extends List[T] {
def mmatch[R](nil: => R, cons: (T, List[T]) => R) = cons(head, tail)
}
def sum(l: List[Int]): Int = l mmatch (
nil = 0,
cons = (x, xs) => x + sum(xs)
)
val list = new Cons(1, new Cons(2, Nil))
println(sum(list))
在这种解释中,当你写
sealed trait List[+T]
case object Nil extends List[Nothing]
case class Cons[+T](head: T, tail: List[T]) extends List[T]
这个词sealed
是提供match
功能的值/术语。
因此,阅读您的问题的一种方式是,为什么不这样做呢?为什么不从其他基本语言特性构建匹配,而不是提供句法匹配呢?
原因是语法match
提供了一些人们喜欢的语法糖:
重叠匹配函数:
sealed trait A
sealed trait B
case object X extends A
case object Y extends A with B
case object Z extends B
嵌套匹配函数:
(1 :: 2 :: Nil) match {
case x :: y :: Nil => ???
}
如果没有语法糖,这是非常尴尬的。你能行的; 在尝试实现单子提取器时,我尝试探索这种可能性;但它肯定不那么漂亮。
自动选择开放式和封闭式匹配功能。
也就是说,Scala 中的提取器类似于开放匹配函数,因为任何都可能因返回而失败None
;编译器不会检查是否完整match
,但您可以根据需要将多个链接在一起,Scala 会选择第一个。另一方面,sealed
特征提供封闭匹配功能,并具有完整性检查的好处。这些需要由单独的函数提供,但 Scala 允许您match
对两者使用相同的语法。
就我个人而言,我怀疑上述要求最终不需要为匹配提供特殊的句法支持。我怀疑其他更通用的语言特性最终会提供同样的好处,尤其是在嵌套匹配领域。match
然而,目前用特殊语法直接解决问题更有意义。