Bri*_*don 4 type-systems scala algebraic-data-types
我刚写了这个函数,想知道如果我省略了Nil的情况会发生什么,并注意到scalac给了我一个警告:
def printList[String](list: List[String]) {
list match {
case head :: tail => {
println(head)
printList(tail)
}
//case Nil => println("Done")
}
}
Run Code Online (Sandbox Code Playgroud)
Warning: match may not be exhaustive.
It would fail on the following input: Nil
我无法确切地确定这里发生了什么.我在递归数据类型上得到了模式匹配的一般概念,直到你耗尽了案例,但我不清楚它是如何映射到Scala类型系统的.具体来说,我正在查看Scala标准库的源代码,并想知道:
它实际上并不像你想象的那么复杂. List是sealed abstract class正好用两个实现,Nil和::(是的,这是类的名称).这里重要的部分是sealed修饰语.这只是强制实现任何实现的类List 必须与List它自己在同一个源文件中.
重要的sealed是,现在编译器确实知道每个可能的实现者List,因此如果您对列表进行模式匹配,编译器可以确定您的模式匹配块是否是详尽的.
最后要意识到的是,有一些语法糖正在进行中::.通常,如果你有一些案例类:
case class Foo(a: String, b: Int)
Run Code Online (Sandbox Code Playgroud)
你会匹配它
x match {
case Foo(a, b) => //...
}
Run Code Online (Sandbox Code Playgroud)
但是,当您的案例类只包含两个成员时,您也可以这样写:
x match {
case a Foo b => //...
}
Run Code Online (Sandbox Code Playgroud)
所以在你的模式匹配语句中,你真的在做:
list match {
case ::(head, tail) => {
Run Code Online (Sandbox Code Playgroud)
所以你真正要做的就是检查列表是否是一个实例::.因此,编译器可以看到您从不检查列表是否是实例Nil并向您发出警告.