Opciones

El tipo de opción de F# se usa cuando es posible que no exista un valor real para un valor o una variable con nombre. Una opción tiene un tipo subyacente y puede contener un valor de ese tipo, o no tener ningún valor.

Comentarios

En el código siguiente se muestra una función que genera un tipo de opción.

let keepIfPositive (a: int) = if a > 0 then Some(a) else None

Como se puede ver, si la entrada a es mayor que 0, se genera Some(a). De lo contrario, se genera None.

El valor None se usa cuando una opción no tiene un valor real. De lo contrario, la expresión Some( ... ) proporciona un valor a la opción. Los valores Some y None resultan útiles en la coincidencia de patrones, como en la siguiente función exists, que devuelve true si la opción tiene un valor y false si no.

let exists (x: int option) =
    match x with
    | Some(x) -> true
    | None -> false

Usar Opciones

Las opciones se suelen usar cuando una búsqueda no devuelve un resultado coincidente, como se muestra en el código siguiente.

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 busca en una lista de forma recursiva. La función tryFindMatch toma una función de predicado pred que devuelve un valor booleano y una lista en la que buscar. Si se encuentra un elemento que satisface el predicado, la recursividad finaliza y la función devuelve el valor como una opción en la expresión Some(head). La recursividad finaliza cuando se empareja la lista vacía. En ese momento no se ha encontrado el valor head y se devuelve None.

Muchas funciones de biblioteca 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 cuando es posible que un valor no exista, por ejemplo, si es posible que se inicie una excepción al intentar 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 porque devuelve un objeto File si el archivo se abre correctamente y None si se produce una excepción. En función de la situación, puede que no sea una opción de diseño adecuada para detectar una excepción en lugar de permitir que se propague.

Además, todavía es posible pasar null o un valor que sea null al caso Some de una opción. Esto suele evitarse y, normalmente, está en la programación de F# rutinaria, pero es posible debido a la naturaleza de los tipos de referencia de .NET.

Propiedades y métodos de opción

El tipo de opción admite las siguientes propiedades y métodos.

Propiedad o método Tipo Descripción
None 'T option Miembro estático que crea un valor de opción que tiene el valor None.
IsNone bool Devuelve true si la opción tiene el valor None.
IsSome bool Devuelve true si la opción tiene un valor que no es None.
Some 'T option Miembro estático que crea una opción que tiene un valor que no es None.
Valor 'T Devuelve el valor subyacente o inicia System.NullReferenceException si el valor es None.

Módulo Option

Hay un módulo, Option, que contiene funciones útiles que realizan operaciones en opciones. Algunas funciones repiten la funcionalidad de las propiedades, pero son útiles en contextos en los que se necesita una función. Option.isSome y Option.isNone son funciones de módulo que comprueban si una opción contiene un valor. Option.get obtiene el valor, si hay uno. Si no hay ningún valor, inicia System.ArgumentException.

La función Option.bind ejecuta una función en el valor, si hay un valor. La función debe tomar exactamente un argumento, y su tipo de parámetro debe ser el tipo de opción. El valor devuelto de la función es otro tipo de opción.

El módulo de opción también incluye funciones que corresponden a las funciones que están disponibles para listas, matrices, secuencias y otros tipos de colecciones. Estas funciones incluyen Option.map, Option.iter, Option.forall, Option.exists, Option.foldBack, Option.fold y Option.count. Estas funciones permiten usar opciones como una colección de cero o un elemento. Para obtener más información y ejemplos, vea la explicación de las funciones de colección en Listas.

Conversión a otros tipos

Las opciones se pueden convertir en listas o matrices. Cuando una opción se convierte en cualquiera de estas estructuras de datos, la estructura de datos resultante tiene cero o un elemento. Para convertir una opción en una matriz, use Option.toArray. Para convertir una opción en una lista, use Option.toList.

Vea también