catching
on dirait que c'est une sorte d'appel de méthode, n'est-ce pas ? C'est le cas, mais il renvoie en fait une instance de la classe Catch
; elle ne prend pas directement un argument. Cette classe possède deux méthodes qui sont particulièrement utiles pour traiter les exceptions (et plusieurs autres pour attraper des exceptions multiples). La première est
def opt [U >: T] (body: ⇒ U) : Option[U]
qui est utilisé ici - vous lui donnez quelque chose qui peut lancer une exception, et il retournera Some(result)
si tout s'est bien passé, et None
si l'exception ciblée a été attrapée :
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 alors traiter cette question avec map
o filter
o getOrElse
ou tout autre moyen que vous utilisez pour traiter les options.
L'autre méthode utile est either
qui renvoie une instance de Left(exception)
si une exception a été levée, et un Right(result)
si elle ne l'était 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 alors utiliser fold
ou le mapper à une option ou tout ce que vous aimez faire avec l'un ou l'autre.
Notez que vous pouvez définir un seul attrapeur et l'utiliser plusieurs fois (vous n'avez donc pas besoin de créer l'objet attrapeur à chaque fois que vous analysez un entier, par exemple) :
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 le fait remarquer dans les commentaires, cela crée toujours un problème temporaire. Catch[Option]
Étant donné les signatures des méthodes, il n'y a pas de moyen facile de faire en sorte qu'elles détectent les exceptions et génèrent des options sans créer d'objets supplémentaires. 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)