Type Option
Présentation
A.k.a Maybe (Haskell), Optional (Java 8)
Modélise l'absence de valeur
→ Dans le sens d'une possibilité pour une valeur d'être absente
→ Différent de unit qui est utilisé dans le cas où il n'y a jamais de valeur
Défini sous la forme d'une union avec 2 cases :
type Option<'Value> =
| None // Case sans donnée → quand valeur absente
| Some of 'Value // Case avec donnée → quand valeur présenteCas d'utilisation
Modéliser un champ optionnel
type Civility = Mr | Mrs
type User = { Name: string; Civility: Civility option }
let joey = { Name = "Joey"; Civility = Some Mr }
let guest = { Name = "Guest"; Civility = None }→ Rend explicite le fait que Name est obligatoire et Civility facultatif
☝ Attention : ce design n'empêche pas ici d'avoir Name = null (limite BCL)
Opération partielle
Opération où aucune valeur de sortie n'est possible pour certaines entrées.
Exemples
Exemple 1 - Inverse d'un nombre
Fonction
Opération
Signature
n = 0.5
n = 0.0
inverse
Partielle
float -> float
2.0
infinity ❓
tryInverse
Totale
float -> float option
Some 2.0
None 👌
Exemple 2 - Recherche d'un élément dans une collection
Opération partielle :
find predicate→ 💥 quand élément non trouvéOpération totale :
tryFind predicate→NoneouSome item
Avantages 👍
Explicite (honnête) concernant la partialité de l'opération
Pas de valeur spéciale (et cachée) :
null,infinityPas d'exception
Force le code appelant à gérer la totalité des cas :
Présence d'une valeur en sortie :
Some valueAbsence d'une valeur en sortie :
None
Flux de contrôle
Pour tester la présence de la valeur (de type 'T) dans l'option
❌ Ne pas utiliser
IsSome,IsNoneetValue(🤞💥)if option.IsSome then option.Value...
👌 A la main avec pattern matching
✅ Fonctions du module
Option
Manuel avec pattern matching
Exemple :
Intégré au module Option
OptionOpération de Mapping de la valeur (de type 'T) si ∃ :
option |> Option.map favecfopération totale'T -> 'Uoption |> Option.bind favecfopération partielle'T -> 'U option
Conserver la valeur si ∃ et si respecte condition :
option |> Option.filter predicateavecpredicate: 'T -> boolappelé que si valeur ∃
Exercice
Implémenter map, bind et filter avec pattern matching
Solution
Réponses 🎁
Exemple
Bénéfices
Rend logique métier + lisible
Pas de
if hasValue then / elseMet en valeur le happy path
Centralise à la fin la gestion de l'absence de valeur
💡 Les 🚀 Computation expression (CE)📍 fournissent une syntaxe alternative + légère
Option vs List
Option vs ListOption ≃ Liste de 0 ou 1 élément → cf. fonction Option.toList
☝ Une List peut avoir + de 1 élément
→ Type Option modélise mieux l'absence de valeur que type List
💡 Module Option : beaucoup de même fonctions que module List
→ contains, count, exist, filter, fold, forall, map
Option vs null
Option vs nullDe part ses interactions avec la BCL, F♯ autorise parfois la valeur null
👉 Bonne pratique
→ Isoler ces cas de figure et wrapper dans un type Option
→ Par exemple en utilisant la fonction Option.ofObj
Option vs Nullable
Option vs NullableType System.Nullable<'T> ≃ Option<'T> en + limité
❗ Ne marche pas pour les types références
❗ Manque comportement monadique i.e. fonctions
mapetbind❗ En F♯, pas de magie comme en C♯ / mot clé
null
👉 Option est le type idiomatique en F♯
💡 On utilise le type Nullable en cas d'interop. Pour l'instancier :
→ ❌ Contrairement au C♯, le mot clé null ne marche pas !
→ 👎 L'emploie de Unchecked.defaultof marche mais n'est pas élégant.
→ 👍 Utiliser l'un des constructeurs : Nullable() ou Nullable(value)
Mis à jour
Ce contenu vous a-t-il été utile ?