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.
Observações
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)
é gerada. 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 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 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 pred
de predicado 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 option
tipo. 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 openFile
função no exemplo anterior tem tipo string -> File option
porque retorna um File
objeto 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 que é 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 da opção
O tipo de opção suporta as seguintes propriedades e métodos.
Propriedade ou método | Tipo | Description |
---|---|---|
None |
'T option |
Um membro estático que cria um valor de opção que tem o None valor. |
IsNone | bool |
Devolve true se a opção tiver o None valor. |
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 |
Devolve o valor subjacente ou lança um System.NullReferenceException se o valor for None . |
Módulo de opção
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 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, se houver. 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.fold
e Option.count
. Essas funções permitem que as opções sejam usadas como uma coleção de zero ou um elemento. Para obter mais informações e exemplos, consulte a discussão sobre funções de coleta 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
.