Então, nossa jornada para o F # continua. O artigo a seguir se concentrará nos tipos de F # que podem ou não ter equivalentes .NET padrão. Esta postagem é sobre tuplas.
O que são tuplas
Uma tupla é um grupo de valores não nomeados, mas ordenados, possivelmente de tipos diferentes.
Criando tuplas
Tuplas são muito fáceis de criar, apenas fazemos algo como o mostrado abaixo. Observe como eu criei um pacote misto de tuplas, algumas das quais números e outras são seqüências de caracteres, e também podemos misturar e combinar os tipos e o número de valores.
let a = (1,2) let b = (1,"cat") let c = (1,"cat") let d = (1,"cat", 'c')
Tuplas universais
As funções que aceitam tuplas também podem aceitar tuplas universais sem problemas. Um sistema de inferência como o F # manipulará com prazer a inferência dos tipos corretos para uma tupla. Aqui está um exemplo.
let someFunction tup = let (x,y) = tup printfn "x is %A and y is %A" xy do someFunction ("cat","dog") do someFunction (11,12)
E aqui estão os resultados da execução acima, onde você pode ver que a função someFunction aceitou e trabalhou com várias tuplas digitadas sem problemas.

Assinaturas de tupla
Até o momento, não tocamos no entendimento das assinaturas de F #; de fato, esse é um tópico ao qual também decidi dedicar uma postagem de blog inteira, pois acredito que é bastante complicada. No entanto, estamos localizados onde estamos, aqui e agora, e estamos estudando tuplas, então agora eu só queria demonstrar como seria a assinatura da tupla.
Suponha que eu declarei as seguintes tuplas na janela FSI:
let a = (1,2) let b = (1,"codfather") let c = (1,"c", 12.5)
E então eu os examinei na janela do FSI; veremos algo assim:
val a : int * int = (1, 2) val b : int * string = (1, "codfather") val c : int * string * float = (1, "c", 12.5)
Isso é interessante, podemos ver algumas coisas aqui, a saber:
- Parênteses não fazem parte de uma assinatura de tipo
- O sistema do tipo F # pode inferir corretamente um tipo com base nos valores contidos na própria tupla.
- A vírgula é substituída por "*"
Portanto, a tupla cristalina fica assim:
let a = (1,2)
Terá a seguinte assinatura:
int * int
Divisão da tupla
Então, vimos como podemos criar tuplas, mas que tal quebrar ou desconstruí-las novamente em valores separados. Isso é possível? Sim claro. Como antes, vamos começar com alguns exemplos:
let (a,b) = (1,2) printfn "(a,b) = (1,2), so value of 'a' should be 1, and it is =%i,\r\n 'b' should be 2, and it is =%i" ab // , , , // let (_,z) = (1,2) printfn "grabbing last value from (1,2) which is = %i" z let (a,b :string) = (1,"cat") printfn "grabbing (1,\"cat\") which has values = %i %s" ab let (a :int,b :string) = (1,"cat") printfn "grabbing (1,\"cat\") which has values = %i %s" ab let (a ,b, c) = (1,"cat", 'c') printfn "grabbing (1,\"cat\",'c') which has values = %i %s %c" abc let first = fst (1, 2) printfn "grabbing fst from (1,2) which has values = %i" first let second = snd (1, 2) printfn "grabbing 2nd from (1,2) which has values = %i" second
Os resultados são impressos em uma janela de console padrão, da seguinte maneira:

Usando Let
Mas como conseguimos as partes individuais? Bem, tudo que você precisa é o código acima, mas vamos dar um exemplo. Suponha que tivéssemos uma tupla como esta:
(1,2)
E eu queria que os valores de ambos os "valores" da tupla estivessem vinculados a alguns novos valores individuais, poderíamos fazer isso:
let (a,b) = (1,2)
Também podemos selecionar apenas os valores que realmente precisamos, o que é feito usando um curinga para peças indesejadas. O que garante a ausência de vinculação de valor desnecessária Aqui está um exemplo:
let (_,z) = (1,2)
Usando as funções de tupla internas
Também há suporte interno para obter o primeiro e o segundo valores de uma tupla. O que pode ser feito usando as
funções "
fst " e "
snd ". Não há suporte para nada além do segundo elemento (esses são provavelmente os casos mais comuns). "
Fst " e "
snd " podem ser usados da seguinte maneira:
let first = fst (1, 2) let second = snd (1, 2)
Agora, quero chamar sua atenção para um caso especial em que podemos ter uma incompatibilidade com o número de valores que estamos tentando explodir em valores individuais. Portanto, isso será algo como um exemplo aqui:
let (a ,b) = (1,"cat", 'c')
Você pode ver que a tupla em si realmente contém 3 valores, mas a ligação Let possui apenas 2 valores; portanto, o compilador nos alerta sobre isso, como você pode ver na captura de tela abaixo:

Criando novas tuplas
Você pode criar novas tuplas a partir de tuplas existentes, é bastante simples, aqui está um exemplo:
let oldOne = (1,2) let (x,y) = oldOne let newOne = (x+1,y+1) printfn "original = %A, and we did this (x+1,y+1)\r\n to obtain newOne = %A" oldOne newOne

Comparação de tuplas
Tuplas são consideradas iguais apenas se
- Eles têm o mesmo número de valores.
- TODOS os valores são considerados iguais (obviamente, podem ser métodos Equals personalizados ou implementações IEquatable personalizadas e similares)
Vamos ver um exemplo simples.
printfn "(1,2) = (3,4) =% b" ((1,2) = (3,4)) printfn "(1,2) = (1,2) =% b" ((1,2) = (1,2)) printfn "('a', 'b') = ('a', 'b') =% b" (('a', 'b') = ('a', 'b')) printfn "('a', 'b') = ('a', 'c') =% b" (('a', 'b') = ('a', 'c'))

De fato, se suas tuplas tiverem comprimentos diferentes (o número de elementos) e você tentar compará-las usando o operador de igualdade “=”, você receberá um aviso:

Padrões de correspondência de tupla
Ainda não lidamos com padrões correspondentes, mas mais tarde veremos um post inteiro sobre esse tópico. Enquanto isso, saiba que essa é uma maneira de corresponder os parâmetros de entrada novamente. Você pode fazer isso para tuplas, da seguinte maneira:
let someFunction tup = match tup with | 1,2 -> printfn "you passed (1,2)" | _,_ -> printfn "you passed some other tuple" do someFunction (11,12) do someFunction (4,5) do someFunction (1,2) do someFunction (13,23)
