Подтвердить что ты не робот

Scala ловушка путаницы

Я недавно видел такой код:

val maybeInt = catching(classOf[NFE]) opt arg.toInt

Что это за opt? Опция? Почему он не использует getOrElse для извлечения значения? В приведенном выше коде будет maybeInt быть None, если выбрано NumberFormatException?

4b9b3361

Ответ 1

catching выглядит как-то вроде вызова метода, не так ли? Это так, но на самом деле возвращает экземпляр класса Catch; он не принимает прямого аргумента. Этот класс имеет два метода, которые особенно полезны для устранения исключений (и еще нескольких для обнаружения нескольких исключений). Первый -

def opt [U >: T] (body: ⇒ U) : Option[U]

который используется здесь, вы даете ему что-то, что может вызвать исключение, и оно вернет Some(result), если все будет в порядке, и None, если целевое исключение было поймано:

scala> type NFE = NumberFormatException
defined type alias NFE

scala> import scala.util.control.Exception._
import scala.util.control.Exception._

scala> catching(classOf[NFE]).opt( "fish".toInt )
res0: Option[Int] = None

scala> catching(classOf[NFE]).opt( "42".toInt )  
res1: Option[Int] = Some(42)

Затем вы можете справиться с этим с помощью map или filter или getOrElse или всего, что вы используете для работы с параметрами.

Другим полезным методом является either, который возвращает экземпляр Left(exception), если выбрано исключение, и Right(result), если это не так:

scala> catching(classOf[NFE]).either( "fish".toInt )
res2: Either[Throwable,Int] = Left(java.lang.NumberFormatException: For input string: "fish")

scala> catching(classOf[NFE]).either( "42".toInt )
res3: Either[Throwable,Int] = Right(42)

Затем вы можете использовать fold или сопоставить параметр или все, что вам нравится делать с eithers.

Обратите внимание, что вы можете определить один улавливатель и использовать его несколько раз (так что вам не нужно создавать объект catcher каждый раз, когда вы, например, разбираете целое число):

scala> val catcher = catching(classOf[NFE])
catcher: util.control.Exception.Catch[Nothing] = Catch(java.lang.NumberFormatException)

scala> catcher.opt("42".toInt)
res4: Option[Int] = Some(42)

scala> catcher.opt("fish".toInt)
res5: Option[Int] = None

Изменить: как отмечает Даниил в комментариях, это создает временный Catch[Option]; учитывая сигнатуры метода, нет простого способа просто исключить исключения ловушки и генерировать параметры без создания каких-либо дополнительных объектов. Это напоминает мне, почему я пишу свои собственные методы, чтобы сделать именно это:

def optNFE[T](t: => T) = try { Some(t) } catch {case nfe: NFE => None}
optNFE( "fish".toInt )  // gives None
optNFE( "42".toInt ) // gives Some(42)

Ответ 2

Я использую более простой шаблон, когда есть только один улов:

 try{
      return args.split(" ").exists(line.startsWith _)
 }catch {
    case _ =>{//generic exception
      logger.error("Error with line ${line} for ${ex.message}")
      throw _
    }    
 }

Я определенно еще не профессионал Scala, и я думаю, вы могли бы найти более короткие вещи