Compartilhar via


Opções

O tipo de opção em F# é usado quando um valor real pode não existir para um valor ou variável nomeado. Uma opção tem um tipo subjacente e pode conter um valor desse tipo ou pode não ter um valor.

Comentários

O código a seguir ilustra uma função que gera um tipo de opção.

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

Como você pode ver, se a entrada a for maior que 0, Some(a) será gerado. Caso contrário, None é gerado.

O valor None é usado quando uma opção não tem um valor real. Caso contrário, a expressão Some( ... ) fornecerá um valor à opção. Os valores Some e None são úteis em padrões correspondentes, como na função exists a seguir, que retorna true se a opção tiver um valor e false se não tiver.

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

Usando opções

As opções são comumente usadas quando uma pesquisa não retorna um resultado correspondente, conforme mostra o código a seguir.

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 ]

No código anterior, uma lista é pesquisada recursivamente. A função tryFindMatch usa uma função de predicado pred que retorna um valor booliano e uma lista a ser pesquisada. Se um elemento que satisfaz o predicado for encontrado, a recursão terminará e a função retornará o valor como uma opção na expressão Some(head). A recursão termina quando a lista vazia é correspondida. Nesse ponto, o valor head não foi encontrado e None é retornado.

Muitas funções de biblioteca F# que pesquisam uma coleção em busca de um valor que pode ou não existir retornam o tipo option. Por convenção, essas funções começam com o prefixo try, por exemplo, Seq.tryFindIndex.

As opções também podem ser úteis quando um valor pode não existir, por exemplo, se for possível que uma exceção seja gerada quando você tenta construir um valor. O exemplo de código a seguir ilustra isso.

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

A função openFile no exemplo anterior tem tipo string -> File option porque retorna um objeto File se o arquivo é aberto com êxito e None se ocorre uma exceção. Dependendo da situação, pode não ser uma opção de design apropriada capturar uma exceção em vez de permitir que ela se propague.

Além disso, ainda é possível passar null ou um valor nulo para o caso Some de uma opção. Isso geralmente deve ser evitado e, normalmente, está na programação F# de rotina, mas é possível devido à natureza dos tipos de referência no .NET.

Propriedades e métodos da opção

O tipo de opção dá suporte às seguintes propriedades e métodos.

Propriedade ou método Tipo Descrição
None 'T option Um membro estático que cria um valor de opção que tem o valor None.
IsNone bool Retornará true se a opção tiver o valor None.
IsSome bool Retornará true se a opção tiver um valor que não seja None.
Some 'T option Um membro estático que cria uma opção que tem um valor que não é None.
Valor 'T Retorna o valor subjacente ou gera um System.NullReferenceException se o valor for None.

Módulo Option

Há um módulo, Option, que contém funções úteis que executam operações em opções. Algumas funções repetem a funcionalidade das propriedades, mas são úteis em contextos em que uma função é necessária. Option.isSome e Option.isNone são funções de módulo que testam se uma opção contém um valor. Option.get obtém o valor, se houver um. Se não houver valor, System.ArgumentException será gerado.

A função Option.bind executa uma função no valor, se houver um valor. A função deve ter exatamente um argumento e seu tipo de parâmetro deve ser o tipo de opção. O valor retornado da função é outro tipo de opção.

O módulo de opção também inclui funções que correspondem às funções disponíveis para listas, matrizes, sequências e outros tipos de coleção. Essas funções incluem Option.map, Option.iter, Option.forall, Option.exists, Option.foldBack, Option.fold e Option.count. Essas funções permitem que as opções sejam usadas como uma coleção de zero ou um elemento. Para mais informações e exemplos, confira a discussão das funções de coleção em Listas.

Como converter em outros tipos

As opções podem ser convertidas em listas ou matrizes. Quando uma opção é convertida em qualquer uma dessas estruturas de dados, a estrutura de dados resultante tem zero ou um elemento. Para converter uma opção em uma matriz, use Option.toArray. Para converter uma opção em uma lista, use Option.toList.

Confira também