Проверьте два конкретных исключения в выражении соответствия в Scala

#scala #exception #pattern-matching

#scala #исключение #сопоставление с образцом

Вопрос:

Поэтому у меня есть блок попыток в Scala

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

Теперь я знаю, что здесь много кода, который нуждается в объяснении. Для целей этого вопроса, однако, необходимо знать следующее:

При создании экземпляра Pitch с заданной заметкой, такой как «D#4», могут быть два разных исключения, которые я хочу специально обработать. Первый-если индекс pitchClassIndex карты не может найти заданное ключевое имя pitchclass, второй — если аргумент Pitch находится за пределами заданного диапазона.

pitchClassIndex:

 val pitchClassIndex: Map[String, Int] = pitchClassNames.zipWithIndex.toMap  

Имена классов PITCH:

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

Поэтому сейчас мы вводим s: String и проверяем есть ли в нем цифра, если так разделить его на кортеж, val (pitchClassName, octaveName) если s = "D#4" кортеж теперь ("D#", "4") val octave = 4 так что теперь при создании нашего поля экземпляра, мы получим значение pitchClassIndex: Map[String, Int] из ключа pitchClassName: String = "D#" (обратите внимание, что если pitchClassName не соответствует значению в pitchClassNames мы получим исключение) мы потом добавить octave: Int = 4 первый умножается на 12. Pitch(51) Теперь две первые строки подачи выглядят так:

 case class Pitch(nbr: Int):  assert((0 to 127) contains nbr, s"Error: nbr $nbr outside (0 to 127)")  

Поэтому, если аргументы, переданные в поле, находятся за пределами диапазона (0 to 127) , то бросьте и подтвердите ошибку с сообщением об ошибке.

Итак, прямо сейчас у нас есть два случая, когда он может выдать исключение, первый-это утверждение в начале. Второй-если pitchClassIndex(pitchClassName) принимает ключ, который не входит, pitchClassNames: Vector[String] например, в «K#». Затем он выдаст исключение NoSuchElementException с сообщением: «ключ не найден: K#»

Теперь, как вы можете видеть, у меня есть пустой случай сбоя в выражении соответствия, где я тестирую оператор Try, в этом случае я хочу проверить, является ли исключение e ошибкой утверждения или исключением NoSuchElementException, и если это одно из них, я хочу напечатать какой-то специальный текст. Последний случай касается других исключений. Однако я не совсем уверен, как это проверить? Есть ли что-то, что я могу написать внутри сбоя, например (e: ???) Есть какие-нибудь идеи?

Ответ №1:

Вы могли бы добавить два предложения по регистру для двух исключений

 case Failure(e: AssertionError) =gt;   // do something case Failure(e: NoSuchElementException) =gt;   // do something else case Failure(e) =gt;  // goes here for other exceptions  

Если вы хотите объединить их только в одном случае, вы больше не сможете фиксировать детали в переменной e , так что это может быть не вариант:

 case Failure(_: AssertionError)   | Failure(_: NoSuchElementException) =gt;   // cannot use `e` anymore   

Я полагаю, вы могли бы прибегнуть к .isInstanceOf

 case Failure(e)   if e.isInstanceOf[AssertionError] ||  e.isInstanceOf[NoSuchElementException] =gt;  // now `e` is Throwable in here