使用scala模式匹配代替java switch case有什么好处?

y53ybaqx  于 2023-01-01  发布在  Java
关注(0)|答案(6)|浏览(156)

每个人都说模式匹配是函数式语言的一个很好的特性,为什么呢?
我不能简单地使用if和交换大小写吗?
我想了解使用模式匹配而不是常规的过程编程if和switch case的优点

m4pnthwp

m4pnthwp1#

首先我想指出的是,你没有使用模式匹配来“代替”switch语句,Scala没有switch语句,它有匹配块,匹配块中的大小写看起来非常类似于switch语句。
使用模式匹配匹配块可以完成switch所做的一切,甚至更多。

A)它不仅限于原语和Oracle在语言规范中选择“祝福”的其他类型(字符串和枚举)。如果你想匹配你自己的类型,那就去吧!
B)模式匹配也可以提取。例如,对于元组:

val tup = ("hello world", 42)
tup match {
  case (s,i) =>
    println("the string was " + s)
    println("the number was " + i
}

有一个列表:

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
}

使用案例类

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)
}

C)模式匹配可以用于赋值和for-解析,而不仅仅是匹配块:

val tup = (19,73)

val (a,b) = tup

for((a,b) <- Some(tup)) yield a+b // Some(92)

D)匹配块是表达式,而不是语句

这意味着它们只对匹配的大小写的主体求值,而不是完全通过副作用来执行。这对于函数式编程来说是至关重要的!

val result = tup match { case (a,b) => a + b }
nom7f22z

nom7f22z2#

不知何故,我对@KevinWright答案的编辑/添加被丢弃了,所以我将在这里添加它作为一个更好的模式匹配功能...

F)编译器对案例的详尽检查。

如果存在一个值匹配,而这个值不被现有的case覆盖,编译器会警告你,这是语言的一个非常好的特性,因为如果你不忽略这些编译器警告,你就不会捕捉到这样的运行时异常,或者遇到你没有想到的case。如果您仍然运行应用程序并忽略警告,则当您的值不匹配任何大小写时,您将获得一个很好的描述性异常。

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$)

在这种情况下,我更喜欢得到一个异常,因为它会失败得很清楚,而且通常会很早,而不是执行意外的逻辑分支。
如果你使用if,你就必须使用else,如果你使用Java switch,你就必须使用default case来覆盖所有的情况。Scala编译器知道在这种情况下空列表和非空列表是不同的,或者更广义地说,你定义了匹配的粒度,你可以匹配1或2个元素的列表,忽略剩下的,或者使用其他更复杂的模式,而不必担心你是否能覆盖所有的情况。
简而言之,当你使用复杂的提取和匹配逻辑时,编译器会确保你不会错过任何大小写。在Java中没有类似的情况,除非你使用默认的大小写,如defaultelse

ni65a41a

ni65a41a3#

模式匹配不是switch语句的替代方法,我认为它是在oop中执行动态调度的另一种方法。它们尝试做同样的事情:基于参数的动态类型调用函数的不同版本

lndjwyie

lndjwyie4#

正如在其他答案中所写的,Scala模式匹配和Java开关并不是一回事。

switch语句:

  • 仅适用于本机类型、枚举类型和String类
  • 根据命令式编程,它可以替代“if-else”链来创建多个执行路径
    模式匹配:
  • 它允许使用第一匹配策略匹配任何类型的数据
  • 它符合功能逻辑:每个case语句返回一个值,并且整个match语句实际上是返回匹配case值的函数。

换句话说,你可以使用“模式匹配”来达到类似于“java开关”的目的,但是在这样做的时候,你是在以一种命令式的方式使用函数工具。

h7appiyu

h7appiyu5#

JMPL是一个简单的java库,它可以使用Java 8特性模拟模式匹配的一些特性。

matches(data).as(
          new Person("man"),    () ->  System.out.println("man");
          new Person("woman"),  () ->  System.out.println("woman");
          new Person("child"),  () ->  System.out.println("child");        
          Null.class,           () ->  System.out.println("Null value "),
          Else.class,           () ->  System.out.println("Default value: " + data)
       );

       matches(data).as(
          Integer.class, i  -> { System.out.println(i * i); },
          Byte.class,    b  -> { System.out.println(b * b); },
          Long.class,    l  -> { System.out.println(l * l); },
          String.class,  s  -> { System.out.println(s * s); },
          Null.class,    () -> { System.out.println("Null value "); },
          Else.class,    () -> { System.out.println("Default value: " + data); }
       );

       matches(figure).as(
          Rectangle.class, (int w, int h) -> System.out.println("square: " + (w * h)),
          Circle.class,    (int r)        -> System.out.println("square: " + (2 * Math.PI * r)),
          Else.class,      ()             -> System.out.println("Default square: " + 0)
       );
taor4pac

taor4pac6#

摘自Martin Odersky(Scala的创建者)和其他人的一本伟大的书Programming in Scala
Java的switch

  • 可以使用整数类型、枚举和常量可以在case中使用
  • break在每个备选项的末尾
  • 没有break,从一个备选方案跌落到下一个备选方案
    *不产生值

Scala的match

  • case中可以使用任何类型的常量以及其他内容
  • 在每个备选项的末尾没有break
  • 从一个选择方案到下一个选择方案不会失败
    *产生一个值
    示例使用Java和Scala编程的相同逻辑:

斯卡拉

firstArg match
  case "salt" => println("pepper")
  case "chips" => println("salsa")
  case "eggs" => println("bacon")
  case _ => println("huh?")

java

switch (firstArg) {
  case "salt":
    System.out.println("pepper");
    break;
  case "chips":
    System.out.println("salsa");
    break;
  case "eggs":
    System.out.println("bacon");
    break;
  default:
    System.out.println("huh?");
}

Scala的match可以产生一个值,Java的switch不能:

friend match
  case "salt" => "pepper"
  case "chips" => "salsa"
  case "eggs" => "bacona"
  case _ => "huh?"

相关问题