Option dans Scala: Au revoir le Null Pointer Exception (NPE)

Scala monadic1-logo

Le but de cet article est de montrer par l'exemple l'intérêt de la notion Option dans scala.

On évoquera aussi la notion flatMap.

Question: Qu'est-ce qu'une Option dans scala?

Comme le mentionne la scaladoc c'est un type qui peut avoir optionnellement une valeur.

Justement le type None indique qu'aucune valeur n'est définie.

Donc le type Option peut avoir deux valeurs Some[A) ou None.

Ainsi, quand le type Option est une Some[A]  elle représente une valeur existante de type A.

PARTIE 1. PROBLÉMATIQUE PAR L'EXEMPLE

Pour introduire l'intérêt de la notion Option, prenons cet exemple simple de liste de String:

val liste=List("A","B",null,"C")

Dans un premier temps je dois convertir cette liste en minuscule.

Le code suivant permet de le faire
liste.map(_.toLowerCase)

Sauf qu'on obtient java.lang.NullPointerException (NPE) , par malchance, cette liste contient un élément null.

Un java.lang.NullPointerException en scala? Oui en scala si on ne recourt pas à la notion Option.

Comment éviter cette NPE ?

Justement la notion Option permet de dire bye bye au NPE.

Car Option précise que deux cas sont possibles:
Cas 1. La variable est renseignée et dans ce cas on peut lire sa valeur.
Cas 2. La variable n'est pas renseignée et dans ce cas elle est tout simplement positionnée None.

Aucune raison de confondre les deux cas puisque dans la signature de l'api on sait que le retour est une Option.

Par exemple, si on voulait transformer la liste précédente en minuscule on peut procéder comme suit:

  1. Transformer les éléments de la liste en Option,
  2. L'élément null de la liste sera donc transformé en None car Option(null)=None,
  3. Utiliser flatMap qui ignore les éléments de la liste qui sont à None,
  4. Enfin on transforme avec map en minuscule.

En faisant de cette manière, nous n'avons aucune raison de rencontrer une NPE puisque flatMap les a bien ignoré.

Ce qui donne ce code :

liste.map(Option(_)). flatMap( item => item).map( _.toLowerCase)

Expliquons un peu:

liste.map(Option(_)) transforme les éléments de la liste en Option. Si un élément est null il est transformé en None.
Le résultat de liste.map(Option(_)) retourne List(Some(A), Some(B), None, Some(C))

flatMap (item => item) ne garde que les éléments qui sont différents de None.
Donc flatMap retourne List(A, B, C). Au passage, flatMap applatit la liste.
Et enfin map(_.toLowerCase) pour changer la classe en minuscule.

L'appel à map(_.toLowerCase) est sécurisé puisqu'on sait qu'aucune NPE ne peut être levée.

PARTIE 2 . OPTION EN PRATIQUE: MATCHING PATTERN

EXEMPLE 1. Option: Exemple simple

val opt=Some("Sample")

val optNone=None

opt match{
case Some(a) => println(a)
case _ => println("none")
}

On peut aussi écrire :

opt.getOrElse("")

ou

optNone.getOrElse("")

Aussi, opt map (_.toLowerCase) retourne : Some(sample)

EXEMPLE 2. Liste d'Option

val list=Lis("AB"," "," CD")

list.map(_.trim).filter(_.length!=0).map(_.toLowerCase) retourne list("ab","cd")

Notez qu'avec for-comprehension on peut écrire de manière équivalente ce code comme suit:
val r=for{
item u x).map(_.trim).filter(_.length!=0).map(_.toLowerCase)

retourne le même résultat: List("ab", "cd")
En effet, le flatMap ignore les None.
le map(_trim) vire les espaces,
le filtre ne garde que les items non vides.
Enfin le dernier map transforme en minuscule.

NOTE. Le dernier élément de la liste est None et non pas null.

RESUME:

Avec Option de scala nous n'avons plus à utiliser l'initialisation avec null. Utilisez à la place None.

Les API dans scala usent de la notion Option : Elles prennent en argument et/ou renvoient des Option.

Je crois qu'il faudrait retenir également de cet article que l'utilisation de flatMap avec Option est utile.
Elle permet d’aplatir la variable Option si on la regarde comme une Liste pour mieux saisir le sens.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.