Comprendre les options dans Scala

Suraj P 30 janvier 2023
  1. le type Option en Scala
  2. Récupérer la valeur de l’Option en Scala
  3. l’Option comme conteneur dans Scala
Comprendre les options dans Scala

Dans cet article, nous allons apprendre à travailler avec des éléments de données facultatifs dans Scala. Les Options de Scala nous aident à écrire du code robuste.

le type Option en Scala

Option[T] dans une Scala est un conteneur stockant zéro ou une valeur d’un type donné. En gérant les valeurs facultatives à l’aide de Option de Scala, nous pouvons garantir deux choses :

  1. Sécurité de type : Nous pouvons paramétrer les valeurs facultatives.
  2. Conscience fonctionnelle : Le type option fournit de nombreuses capacités fonctionnelles qui garantissent que moins de bogues sont créés dans le programme.

Dans Scala, une Option[T] est représentée soit par un objet Some[T] ou None[T]. Ici scala.Option est la classe de base qui est abstraite et étendue, ce qui fait que Option dans Scala se comporte comme un conteneur.

Rappelons que la classe Option et ses sous-classes nécessitent un type concret. Ils peuvent être explicites ou déduits comme la syntaxe suivante.

Exemple:

val obj1: Option[Int] = None
val obj2 = Some(100)

Ici obj1 et obj2 sont des objets de Option[Int]. Une question courante est de savoir comment vérifier si notre Option est Some ou None ?

Pour résoudre ce problème, nous avons les fonctions suivantes.

  1. isEmpty : cette méthode renvoie true si l’objet est None.
  2. nonEmpty : cette méthode renvoie true si l’objet est Some.
  3. isDefined : cette méthode renvoie true si l’objet est Some.

Récupérer la valeur de l’Option en Scala

Nous pouvons utiliser la méthode get pour récupérer la valeur Options. Si la méthode get est invoquée sur un objet de None, alors NoSuchElementException est levée, également appelée biais de succès.

Exemple de code :

val obj1: Option[Int]= ...

val v1 = if (obj1.isDefined)
{
  obj1.get
}
else
{
  0
}

Le code ci-dessus peut également être écrit en utilisant la correspondance de modèle.

Exemple de code :

val obj1: Option[Int]= ...

val v1 = obj1 match {
  case Some(temp) =>
    temp
  case None =>
    0
}

Nous avons aussi d’autres méthodes comme getOrElse et orElse pour récupérer des valeurs.

  1. getOrElse : Cette méthode récupère des valeurs si l’objet est Some ; sinon, il renvoie une valeur par défaut.
  2. orElse : Cette méthode récupère des valeurs si l’objet est Some ; sinon renvoie une alternate Option.

Lorsque la valeur optionnelle n’est pas définie, la méthode getOrElse est très utile car nous pouvons renvoyer une valeur par défaut.

Syntaxe:

val v1 = obj1.getOrElse(0)

l’Option comme conteneur dans Scala

Comme nous avons vu que Option est un conteneur dans Scala pour une autre valeur, tout comme nous parcourons une List de la même manière, nous pouvons parcourir une Option.

Regardons quelques méthodes pour ce conteneur. Syntaxe de la méthode Option.map en Scala :

final def map[Y](f: (X) => Y): Option[Y]

Exemple de code :

val obj1: Option[Int] = Some(100)
assert(obj1.map(_.toString).contains("100"))
assert(obj1.map(_ * 2.0).contains(200))

val obj2: Option[Int] = None
assert(obj2.map(_.toString).isEmpty)

Dans l’exemple ci-dessus, nous avons utilisé la méthode Option.map pour convertir les valeurs contenues dans un autre type. La méthode Option.map pourrait également être utilisée pour affecter le contrôle de flux du programme.

Exemple de code :

val obj1: Option[Int] = Some(10)
val obj2: Option[Int] = None

def mul(n: Int): Int = n * 2

assert(obj1.map(mul).contains(20))
assert(obj2.map(mul).isEmpty)

Ici, nous avons créé deux objets de Option[Int], le premier objet a une valeur de 10, et le second est vide. Puis nous avons défini une méthode mul qui multiplie l’entrée par 2.

Enfin, nous mappons obj1 et obj2 en utilisant la méthode mul. Le mapping obj1 nous donne Some(20), et le mapping obj2 nous donne None.

Une chose à observer ici est que dans le second appel, obj2.map(mul), la méthode mul n’est pas appelée du tout. Nous pouvons également contrôler le flux avec filtrage.

Nous avons plusieurs méthodes pour le faire :

  1. filter : Cette méthode renvoie Option si la valeur Options est Some et la fonction fournie renvoie true.
  2. exists : cette méthode renvoie true si l’Option est définie et que la fonction fournie renvoie true.
  3. forall : se comporte de la même manière que la méthode exists.

En utilisant ces fonctions, nous pouvons écrire le code de manière très concise.

Prenons un exemple où nous trouvons l’équipe qui a obtenu le meilleur score.

Exemple de code :

 def highScoringTeam(playerA: Player, playerB: Player, tournament: Tournament): Option[(Player, Int)] =
 { getTopScore(playerA, tournament).foldRight(getTopScore(playerB, tournament)) {
      case (playerAInfo, playerBInfo) => playerBInfo.filter {
        case (_, scoreB) => scoreB > playerAInfo._2
      }.orElse(Some(playerAInfo))
    }
  }

Dans le code ci-dessus, nous avons tiré parti du fait que Options peut être utilisé comme collections. La seule différence est qu’une option peut avoir au plus une valeur.

Auteur: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub