Options
Le type d’option en F# est utilisé lorsqu’une valeur réelle n’existe peut-être pas pour une valeur nommée ou une variable. Une option a un type sous-jacent et peut contenir une valeur de ce type, ou elle n’a peut-être pas de valeur.
Remarques
Le code suivant illustre une fonction qui génère un type d’option.
let keepIfPositive (a: int) = if a > 0 then Some(a) else None
Comme vous pouvez le voir, si la a
d’entrée est supérieure à 0, Some(a)
est générée. Sinon, None
est généré.
La valeur None
est utilisée lorsqu’une option n’a pas de valeur réelle. Sinon, l’expression Some( ... )
donne à l’option une valeur. Les valeurs Some
et None
sont utiles dans la mise en correspondance des modèles, comme dans la fonction suivante exists
, qui retourne true
si l’option a une valeur et false
si ce n’est pas le cas.
let exists (x: int option) =
match x with
| Some(x) -> true
| None -> false
Utilisation des options
Les options sont couramment utilisées lorsqu’une recherche ne retourne pas de résultat correspondant, comme indiqué dans le code suivant.
let rec tryFindMatch pred list =
match list with
| head :: tail -> if pred (head) then Some(head) else tryFindMatch pred tail
| [] -> None
// result1 is Some 100 and its type is int option.
let result1 = tryFindMatch (fun elem -> elem = 100) [ 200; 100; 50; 25 ]
// result2 is None and its type is int option.
let result2 = tryFindMatch (fun elem -> elem = 26) [ 200; 100; 50; 25 ]
Dans le code précédent, une liste est recherchée de manière récursive. La fonction tryFindMatch
prend une fonction de prédicat pred
qui retourne une valeur booléenne et une liste à rechercher. Si un élément qui satisfait le prédicat est trouvé, la récursivité se termine et la fonction retourne la valeur en tant qu’option dans l’expression Some(head)
. La récursivité se termine lorsque la liste vide est trouvée. À ce stade, la valeur head
n’a pas été trouvée et None
est retournée.
De nombreuses fonctions de bibliothèque F# qui recherchent une collection pour une valeur susceptible ou non d’exister retournent le type option
. Par convention, ces fonctions commencent par le préfixe try
, par exemple, Seq.tryFindIndex
.
Les options peuvent également être utiles lorsqu’une valeur n’existe pas, par exemple s’il est possible qu’une exception soit levée lorsque vous essayez de construire une valeur. L’exemple de code suivant illustre cela.
open System.IO
let openFile filename =
try
let file = File.Open(filename, FileMode.Create)
Some(file)
with ex ->
eprintf "An exception occurred with message %s" ex.Message
None
La fonction openFile
dans l’exemple précédent a un type string -> File option
car elle retourne un objet File
si le fichier s’ouvre correctement et None
si une exception se produit. Selon la situation, il peut ne pas s’agir d’un choix de conception approprié pour intercepter une exception plutôt que de l’autoriser à se propager.
De plus, il est toujours possible de passer null
ou une valeur nulle au cas Some
d'une option. Cela est généralement à éviter, et généralement dans la programmation F# de routine, mais est possible en raison de la nature des types de référence dans .NET.
Propriétés et méthodes des options
Le type d’option prend en charge les propriétés et méthodes suivantes.
Propriété ou méthode | Type | Description |
---|---|---|
None |
'T option |
Membre statique qui crée une valeur d’option qui a la valeur None . |
IsNone | bool |
Retourne true si l’option a la valeur None . |
IsSome | bool |
Retourne true si l’option a une valeur qui n’est pas None . |
Some |
'T option |
Membre statique qui crée une option qui a une valeur qui n’est pas None . |
Valeur | 'T |
Retourne la valeur sous-jacente ou génère une exception System.NullReferenceException si la valeur est None . |
Module d’option
Il existe un module, Option, qui contient des fonctions utiles qui effectuent des opérations sur les options. Certaines fonctions répètent les fonctionnalités des propriétés, mais sont utiles dans les contextes où une fonction est nécessaire. Option.isSome et Option.isNone sont les deux fonctions de module qui testent si une option contient une valeur. Option.get obtient la valeur, s'il y en a une. S’il n’existe aucune valeur, il génère System.ArgumentException
.
La fonction Option.bind exécute une fonction sur la valeur, s’il existe une valeur. La fonction doit prendre exactement un argument, et son type de paramètre doit être le type d’option. La valeur de retour de la fonction est un autre type d’option.
Le module d’option inclut également des fonctions qui correspondent aux fonctions disponibles pour les listes, les tableaux, les séquences et d’autres types de collection. Ces fonctions incluent Option.map
, Option.iter
, Option.forall
, Option.exists
, Option.foldBack
, Option.fold
et Option.count
. Ces fonctions permettent d’utiliser des options comme une collection de zéro ou d'un seul élément. Pour plus d’informations et d’exemples, consultez la discussion sur les fonctions de collection dans Lists.
Conversion vers d'autres types
Les options peuvent être converties en listes ou tableaux. Lorsqu’une option est convertie en l’une de ces structures de données, la structure de données résultante a zéro ou un élément. Pour convertir une option en tableau, utilisez Option.toArray
. Pour convertir une option en liste, utilisez Option.toList
.
Conversion d’options avec des valeurs par défaut
Outre la conversion en listes et tableaux, les options peuvent être converties en d’autres types en fournissant des valeurs par défaut à l’aide de la fonction Option.defaultValue
. Cela est particulièrement utile lorsque vous souhaitez vous assurer que la valeur n’est pas None
. Par exemple:
let optionString = Some("F#")
let defaultString = optionString |> Option.defaultValue ""
// defaultString is "F#"
let optionInt = None
let defaultInt = optionInt |> Option.defaultValue 0
// defaultInt is 0
La fonction Option.defaultValue
vous permet de gérer les cas Some
et None
en toute transparence sans correspondance de modèle.