Partilhar via


Opções

O tipo de opção em F# é usado quando um valor real pode não existir para um valor nomeado ou variável. 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 o a de entrada 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( ... ) dá um valor à opção. Os valores Some e None são úteis na correspondência de padrões, como na função a seguir exists, 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 normalmente usadas quando uma pesquisa não retorna um resultado correspondente, conforme mostrado no 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 booleano e uma lista para pesquisar. Se um elemento que satisfaz o predicado for encontrado, a recursão termina e a função retorna 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 por 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 lançada 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 for aberto com êxito e None se ocorrer uma exceção. Dependendo da situação, pode não ser uma escolha 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 Some caso 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 das opções

O tipo de opção suporta as 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.
ÉNenhum bool Retorna true se a opção tiver o valor None.
IsSome bool Retorna true se a opção tiver um valor que não é 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 lança um System.NullReferenceException se o valor for None.

Módulo de opção

Existe 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 onde uma função é necessária. Option.isSome e Option.isNone são funções de módulo que testam se uma opção mantém um valor. Option.get obtém o valor, caso exista. Se não houver valor, lança System.ArgumentException.

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 de retorno 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.folde Option.count. Essas funções permitem que as opções sejam usadas como uma coleção contendo zero ou um único elemento. Para obter mais informações e exemplos, consulte a discussão sobre funções de coleção em Listas.

Convertendo para 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.

Convertendo opções com valores padrão

Além de converter em listas e matrizes, as opções podem ser convertidas em outros tipos, fornecendo valores padrão usando a função Option.defaultValue. Isso é particularmente útil quando você deseja garantir que o valor não seja None. Por exemplo:

let optionString = Some("F#")
let defaultString = optionString |> Option.defaultValue ""
// defaultString is "F#"

let optionInt = None
let defaultInt = optionInt |> Option.defaultValue 0
// defaultInt is 0

A função Option.defaultValue permite que se lide facilmente com os casos Some e None, sem a combinação de padrões.

Ver também