Скала ловит растерянность - PullRequest
28 голосов
/ 20 апреля 2011

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

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

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

Ответы [ 2 ]

35 голосов
/ 20 апреля 2011

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 или сопоставить с параметром иливсе, что вам нравится делать с любым из них.

Обратите внимание, что вы можете определить один элемент catcher и использовать его несколько раз (поэтому вам не нужно создавать объект 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)
0 голосов
/ 30 мая 2014

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

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

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

...