Dan*_*ier 9 java functional-programming scala pattern-matching
每个人都说模式匹配是函数式语言的一个很好的特性.为什么?
我不能简单地使用ifs和切换案例的一切吗?
我想了解使用模式匹配而不是常规过程编程ifs和switch case的优点
Kev*_*ght 22
我首先要注意的是,你不要使用模式匹配"代替"switch语句.Scala没有switch语句,它具有的是匹配块,内部的情况看起来非常类似于switch语句.
具有模式匹配的匹配块可以完成所有switch功能,以及更多功能.
A)它不仅限于Oracle在语言规范(Strings and Enums)中选择"祝福"的原语和其他类型.如果你想匹配自己的类型,请继续前进!
B)模式匹配也可以提取.例如,使用元组:
val tup = ("hello world", 42)
tup match {
case (s,i) =>
println("the string was " + s)
println("the number was " + i
}
Run Code Online (Sandbox Code Playgroud)
有一个清单:
val xs = List(1,2,3,4,5,6)
xs match {
case h :: t =>
// h is the head: 1
// t is the tail: 2,3,4,5,6
// The :: above is also an example of matching with an INFIX TYPE
}
Run Code Online (Sandbox Code Playgroud)
有一个案例类
case class Person(name: String, age: Int)
val p = Person("John Doe", 42)
p match {
case Person(name, 42) =>
//only extracting the name here, the match would fail if the age wasn't 42
println(name)
}
Run Code Online (Sandbox Code Playgroud)
C)模式匹配可以用于值赋值和for-comprehension,而不仅仅是匹配块:
val tup = (19,73)
val (a,b) = tup
for((a,b) <- Some(tup)) yield a+b // Some(92)
Run Code Online (Sandbox Code Playgroud)
D)匹配块是表达式,而不是语句
这意味着他们评估匹配的案件的主体,而不是完全通过副作用.这对函数式编程至关重要!
val result = tup match { case (a,b) => a + b }
Run Code Online (Sandbox Code Playgroud)
不知何故,我对@KevinWright回答的编辑/添加被抛弃了,所以我将它添加到这里作为一个更好的模式匹配功能...
F)编译器详尽检查案例.
如果存在与现有案例不涵盖的值匹配,编译器将向您发出警告.这是该语言的一个非常好的功能,因为如果您不忽略这些编译器警告,您将不会捕获此类运行时异常或遇到您没有想到的情况.如果仍然运行应用程序并忽略警告,如果您的值与任何情况都不匹配,您将获得一个很好的描述性异常.这是一个例子:
scala> def badMatch(l: List[Int]): Unit = l match { case x :: xs => println(x) }
<console>:7: warning: match may not be exhaustive.
It would fail on the following input: Nil
def badMatch(l: List[Int]): Unit = l match { case x :: xs => println(x) }
^
badMatch: (l: List[Int])Unit
scala> badMatch(List(1, 2))
1
scala> badMatch(Nil)
scala.MatchError: List() (of class scala.collection.immutable.Nil$)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我更喜欢得到一个例外,因为它会失败并且通常很早,而不是执行意外的逻辑分支.
如果您使用if,则必须使用else,如果您使用Java switch,则必须有default案例来涵盖所有情况.但请注意区别:在这种情况下,Scala编译器知道您的空列表与非空列表不同,或者更广泛地说,您定义匹配的粒度.您可以将列表与1或2个元素匹配并忽略其余元素,或使用任何其他更复杂的模式,而不必担心是否设法覆盖所有情况.
简而言之,当您使用复杂的提取和匹配逻辑时,编译器将确保您不会错过任何案例.除非你使用像default或的默认情况,否则在Java中没有类似的东西else.