28 votes

Scala attrape la confusion

J'ai récemment vu du code comme celui-ci:

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

Qu'est-ce que ce opt ? Une option? Pourquoi n'utilise-t-il pas getOrElse pour extraire la valeur? Dans le code ci-dessus, maybeInt sera-t-il None si une exception NumberFormatException est levée?

32voto

Rex Kerr Points 94401

catching ressemble à une sorte d'appel de la méthode, n'est-ce pas? Il est, mais il retourne en fait une instance d'une classe Catch; il n'est pas directement prendre un argument. Cette classe a deux méthodes qui sont particulièrement utiles pour traiter les exceptions (et plusieurs autres pour la capture de plusieurs exceptions). La première est

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

qui est utilisé ici, de vous donner quelque chose qui peut lancer une exception, et il sera de retour Some(result) si tout s'est bien passé, et None si l'obligation d'exception a été pris:

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)

Vous pouvez ensuite traiter avec cette avec map ou filter ou getOrElse ou autre chose que vous utiliser pour traiter avec les options.

L'autre méthode utile est - either, ce qui renvoie une instance de Left(exception) si une exception a été levée, et un Right(result) s'il ne l'est pas:

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)

Vous pouvez ensuite utiliser fold ou d'une carte à une option ou tout autre chose que vous aimez faire avec eithers.

Notez que vous pouvez définir un seul receveur et de l'utiliser plusieurs fois (si vous n'avez pas besoin de créer le receveur de l'objet à chaque fois que vous, par exemple, l'analyse d'un nombre entier):

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

Edit: comme Daniel points dans les commentaires, cela crée tout de même un temporaire Catch[Option]; compte tenu de la méthode de signatures, il n'y a pas un moyen facile de l'avoir juste piège d'exceptions et de générer des options sans créer des objets en plus. Cela me rappelle pourquoi j'écris mes propres méthodes pour faire exactement cela:

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

0voto

Nicolas Zozol Points 1514

J'utilise un modèle plus simple lorsqu'il n'y a qu'un seul hic:

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

Je ne suis définitivement pas encore un pro de Scala, et je suppose que vous pourriez trouver des trucs plus courts

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by: