检查 Scala 中匹配表达式中的两个特定异常

Fel*_*lis 0 scala exception pattern-matching

所以我在 Scala 中有一个 Try 块

  def fromString(s: String): Option[Pitch] = scala.util.Try {
    val (pitchClassName, octaveName) = s.partition(c => !c.isDigit)
    val octave = if octaveName.nonEmpty then octaveName.toInt else 5
    Pitch(pitchClassIndex(pitchClassName) + octave  * 12)
  } match {
    case scala.util.Success(value) => Some(value)
    case scala.util.Failure(e) => 
    case scala.util.Failure(e) => throw e
  }
Run Code Online (Sandbox Code Playgroud)

现在,我知道这里有很多代码需要解释。为了这个问题的目的,需要知道的是:

当使用给定音符(如“D#4”)创建 Pitch 实例时,可能有两个我想要专门处理的不同异常。第一个是如果映射的pitchClassIndex 找不到给定的键pitchClassName,第二个是如果Pitch 参数超出给定范围。

音高等级索引:

val pitchClassIndex: Map[String, Int] = pitchClassNames.zipWithIndex.toMap
Run Code Online (Sandbox Code Playgroud)

音调类别名称:

val pitchClassNames: Vector[String] = Vector("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
Run Code Online (Sandbox Code Playgroud)

所以现在我们输入s: String并检查它是否有数字,如果有的话将其拆分到元组中val (pitchClassName, octaveName)如果s = "D#4"元组现在是那么现在在创建我们的 Pitch 实例时我们将从键中("D#", "4") val octave = 4获取值(这里请注意,如果pitchClassName不对应到pitchClassNames中的值我们会得到一个异常)然后我们将first乘以12相加 。现在Pitch的前两行看起来像这样:pitchClassIndex: Map[String, Int]pitchClassName: String = "D#"octave: Int = 4Pitch(51)

case class Pitch(nbr: Int):
  assert((0 to 127) contains nbr, s"Error: nbr $nbr outside (0 to 127)")
Run Code Online (Sandbox Code Playgroud)

因此,如果传递给 Pitch 的参数超出范围(0 to 127),则抛出 AssertionError 并带有错误消息。

所以现在我们有两种情况可以抛出异常,第一种是开头的断言。第二个是如果采用未包含在例如“K#”pitchClassIndex(pitchClassName)中的密钥。pitchClassNames: Vector[String]然后它将抛出 NoSuchElementException 并显示消息:“找不到密钥:K#”

现在,如您所见,我在匹配表达式中有一个空的失败情况,我在其中测试 Try 语句,在这种情况下,我想检查异常 e 是否是 AssertionError 或 NoSuchElementException,如果它是其中之一,我想打印一些特殊的内容文本。最后一种情况是针对其他例外情况。但是我不太确定如何测试这个?我可以在失败中写一些东西,例如(e:???)有什么想法吗?

Thi*_*ilo 5

您可以为这两个例外添加两个 case 子句

case Failure(e: AssertionError) => 
  // do something
case Failure(e: NoSuchElementException) => 
  // do something else
case Failure(e) =>
  // goes here for other exceptions
Run Code Online (Sandbox Code Playgroud)

如果您只想将它​​们合并为一种情况,则无法再捕获变量中的详细信息e,因此这可能不是一种选择:

case Failure(_: AssertionError) 
      | Failure(_: NoSuchElementException)     => 
   // cannot use `e` anymore 
Run Code Online (Sandbox Code Playgroud)

我想你可以求助于.isInstanceOf

case Failure(e) 
  if e.isInstanceOf[AssertionError] ||
     e.isInstanceOf[NoSuchElementException] =>
   // now `e` is Throwable in here  
Run Code Online (Sandbox Code Playgroud)