Opciones (F#)
En F#, se utiliza el tipo option cuando es posible que no exista un valor real para un valor con nombre o una variable. Una opción tiene un tipo subyacente y puede contener un valor de ese tipo o puede no tener ningún valor.
Comentarios
En el código siguiente se muestra el uso del tipo de opción.
let keepIfPositive (a : int) = if a > 0 then Some(a) else None
Se utiliza el valor None cuando una opción no tiene un valor. De lo contrario, la expresión Some( ... ) proporciona un valor a la opción. Los valores Some y None son útiles en la coincidencia de modelos, como en la siguiente función exists, que devuelve true si la opción tiene un valor y devuelve false en caso contrario.
let exists (x : int option) =
match x with
| Some(x) -> true
| None -> false
Usar opciones
Las opciones suelen usarse cuando una búsqueda no devuelve ninguna coincidencia, tal y como se muestra en el siguiente código.
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 ]
En el código anterior, se realiza una búsqueda recursiva en una lista. La función tryFindMatch toma una función de predicado pred que devuelve un valor booleano y una lista en la que se va a realizar la búsqueda. Si se encuentra un elemento que cumple el predicado, finaliza la recursión y la función devuelve el valor como una opción en la expresión Some(head). La recursión finaliza cuando se detecta una lista vacía. En ese punto, no se ha encontrado el valor head, por lo que se devuelve None.
Un gran número de las funciones de F# que buscan en una colección un valor que puede o no existir devuelven el tipo option. Por convención, estas funciones comienzan con el prefijo try; por ejemplo, Seq.tryFindIndex.
Las opciones también pueden resultar útiles si existe la posibilidad de que un valor no exista; por ejemplo, si es posible que se produzca una excepción cuando se intenta construir un valor. En el siguiente ejemplo código se muestra cómo hacerlo.
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 función openFile del ejemplo anterior tiene el tipo string -> File option, ya que devuelve un objeto File si el archivo se abre correctamente y devuelve None si se produce una excepción. Según el caso, es posible que, desde el punto de vista del diseño, no sea apropiado optar por la detección de una excepción en lugar de permitir su propagación.
Propiedades y métodos de las opciones
El tipo option admite los siguientes métodos y propiedades.
Propiedad o método |
Tipo |
Descripción |
---|---|---|
'T option |
Propiedad estática que permite crear una opción cuyo valor es None. |
|
bool |
Devuelve true si la opción tiene el valor None. |
|
bool |
Devuelve true si la opción tiene un valor distinto de None. |
|
'T option |
Miembro estático que crea una opción cuyo valor es distinto de None. |
|
'T |
Devuelve el valor subyacente o produce una excepción NullReferenceException si el valor es None. |
Módulo Option
El módulo Option contiene funciones útiles para realizar operaciones con las opciones. Algunas funciones repiten la funcionalidad de las propiedades pero son útiles en los contextos donde se necesita una función. Option.isSome y Option.isNone son funciones de módulo que comprueban si una opción tiene un valor. Option.get obtiene el valor si hay alguno. En caso contrario, produce una excepción ArgumentException.
La función Option.bind aplica una función al valor en caso de que lo haya. La función debe tomar exactamente un argumento y su parámetro debe ser de tipo option. El valor devuelto de la función es otro tipo option.
El módulo de opción también incluye funciones que corresponden a las funciones que están disponibles para las listas, matrices, secuencias y otros tipos de colección. Entre estas funciones se encuentran Option.map, Option.iter, Option.forall, Option.exists, Option.foldBack, Option.fold y Option.count. Estas funciones permiten utilizar las opciones como una colección de uno o cero elementos. Para obtener más información y ejemplos, vea la sección referente a las funciones de colección enListas.
Convertir en otros tipos
Las opciones se pueden convertir en listas o matrices. Cuando se convierte una opción en cualquiera de estas estructuras de datos, la estructura de datos resultante tiene uno o cero elementos. Para convertir una opción en una matriz, utilice Option.toArray. Para convertir una opción en una lista, utilice Option.toList.