web-dev-qa-db-fra.com

Obtenir une valeur d'option ou lever une exception

Étant donné une option, quel est le moyen idiomatique d'obtenir sa valeur ou de lancer une exception en essayant?

def foo() : String = {
  val x : Option[String] = ...
  x.getOrException()
}
66
ripper234

(EDIT: ce n’est pas la meilleure façon ni la plus idiomatique de le faire. Je l’ai écrit quand je n’étais pas familier avec Scala. Je le laisse ici pour un exemple montrant comment non pour le faire. Aujourd'hui, je ferais comme @TravisBrown)

Je pense que cela se résume vraiment à deux choses:

  • comment bien sûr es-tu que la valeur est là?
  • comment voulez-vous réagir si ce n'est pas le cas?

Si à ce stade de votre code vous attendez la valeur doit être présente, et dans le cas distant que ce n'est pas vous voulez que votre programme soit échec rapidement, alors je faites seulement un get normal et laissez Scala lancer un NoSuchElementException s'il n'y avait pas de valeur:

 def foo (): String = {
 val x: Option [String] = ... 
 x.get 
} 

Si vous voulez traiter le cas différemment (jetez votre propre exception), je pense qu'une manière plus élégante ressemblerait à ceci:

 def foo (): String = {
 val x: Option [String] = Aucune 
 x correspond à {
 casse Some (valeur) => valeur 
 cas Aucun => lancer la nouvelle exception MyRuntimeException ("blah") 
} 
} 

Et bien sûr, si vous souhaitez fournir votre propre valeur alternative pour le cas où la Option est None, vous utiliseriez simplement getOrElse:

 def foo (): String = {
 val x: Option [String] = Aucune 
 x.getOrElse ("ma valeur alternative") 
} 
42
Sebastian N.

Une "instruction" throw est en réalité une expression en Scala et a le type Nothing , qui est un sous-type de tout autre type. Cela signifie que vous pouvez simplement utiliser un vieux getOrElse:

def myGet[A](oa: Option[A]) = oa.getOrElse(throw new RuntimeException("Can't."))

Vous ne devriez vraiment vraiment pas faire cela, cependant.

113
Travis Brown

Utilisez simplement la méthode .get. 

def get[T](o:Option[T]) = o.get

Il lève une exception NoSuchElementException si o est une instance de None. 

En gros, je travaillerais avec des options comme celle-ci:

def addPrint(oi:Option[Int]) = oi.map(_+1).foreach(println)
addPrint(Some(41))
addPrint(Some(1336))
addPrint(None)

pour éviter votre question spécifique.

13
Felix

Je pense que cela vous aidera à rester du côté "fonctionnel" :)

TL; DR

  • Lancer Exception pour signaler un échec imprévu dans un code purement fonctionnel.
  • Utilisez Option pour renvoyer des valeurs facultatives.
  • Utilisez Option(possiblyNull) pour éviter les instances de Some(null).
  • Utilisez Either pour signaler un échec prévu.
  • Utilisez Try plutôt que Either pour renvoyer des exceptions.
  • Utilisez Try plutôt qu'un bloc catch pour gérer les échecs inattendus.
  • Utilisez Try lorsque vous travaillez avec Future.
  • Exposer Try dans une API publique a un effet similaire à celui d'une exception vérifiée. Pensez à utiliser des exceptions à la place.

À propos de Either et Try

7
Albert Bikeev

Scala prend désormais en charge cette opération sur les cartes utilisant la méthode getOrElse(), voir documentation here

Comme nous l’avons déjà souligné, le fait de lancer une exception dans Scala est également une expression.

Donc, vous pouvez faire ce qui suit:

myMap.getOrElse(myKey, throw new MyCustomException("Custom Message HERE")
0
Mhd.Tahawi