#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