Tuplas

Uma tupla é um agrupamento de valores não nomeados, mas ordenados, possivelmente de tipos diferentes. As tuplas podem ser tipos de referência ou structs.

Sintaxe

(element, ... , element)
struct(element, ... ,element )

Comentários

Cada elemento na sintaxe anterior pode ser qualquer expressão F# válida.

Exemplos

Exemplos de tuplas incluem pares, triplos etc. de tipos iguais ou diferentes. Alguns exemplos são ilustrados no código a seguir.

(1, 2)

// Triple of strings.
("one", "two", "three")

// Tuple of generic types.
(a, b)

// Tuple that has mixed types.
("one", 1, 2.0)

// Tuple of integer expressions.
(a + 1, b + 1)

// Struct Tuple of floats
struct (1.025f, 1.5f)

Obtendo valores individuais

Você pode usar padrões correspondentes para acessar e atribuir nomes para elementos de tupla, conforme mostrado no código a seguir.

let print tuple1 =
   match tuple1 with
    | (a, b) -> printfn "Pair %A %A" a b

Você também pode desconstruir uma tupla por meio de padrões correspondentes fora de uma expressão match por meio da associação de let:

let (a, b) = (1, 2)

// Or as a struct
let struct (c, d) = struct (1, 2)

Ou você pode fazer a correspondência padrão em tuplas como entradas para funções:

let getDistance ((x1,y1): float*float) ((x2,y2): float*float) =
    // Note the ability to work on individual elements
    (x1*x2 - y1*y2) 
    |> abs 
    |> sqrt

Se você precisar de apenas um elemento da tupla, o caractere curinga (o sublinhado) poderá ser usado para evitar a criação de um novo nome para um valor desnecessário.

let (a, _) = (1, 2)

Copiar elementos de uma tupla de referência em uma tupla de struct também é simples:

// Create a reference tuple
let (a, b) = (1, 2)

// Construct a struct tuple from it
let struct (c, d) = struct (a, b)

As funções fst e snd (somente tuplas de referência) retornam o primeiro e o segundo elementos de uma tupla, respectivamente.

let c = fst (1, 2)
let d = snd (1, 2)

Não há uma função interna que retorna o terceiro elemento de um triplo, mas você pode escrever uma facilmente, como descrito a seguir.

let third (_, _, c) = c

Geralmente, é melhor usar padrões correspondentes para acessar elementos de tupla individuais.

Usando tuplas

As tuplas são uma maneira conveniente de retornar vários valores de uma função, conforme mostrado no exemplo a seguir. Esse exemplo executa a divisão de inteiro e retorna o resultado arredondado da operação como um primeiro membro de um par de tuplas e o restante como um segundo membro do par.

let divRem a b =
   let x = a / b
   let y = a % b
   (x, y)

As tuplas também podem ser usadas como argumentos de função quando você deseja evitar o currying implícito de argumentos de função que está implícito na sintaxe usual da função.

let sumNoCurry (a, b) = a + b

A sintaxe usual para definir a função let sum a b = a + b permite que você defina uma função que é a aplicação parcial do primeiro argumento da função, conforme mostrado no código a seguir.

let sum a b = a + b

let addTen = sum 10
let result = addTen 95
// Result is 105.

Usar uma tupla como parâmetro desabilita o currying. Para obter mais informações, confira "Aplicação parcial dos argumentos", em Funções.

Nomes de tipos de tupla

Quando você escreve o nome de um tipo que é uma tupla, usa o símbolo * para separar os elementos. Para uma tupla que consiste em int, float e string, como (10, 10.0, "ten"), o tipo seria escrito como o exemplo a seguir.

int * float * string

Parênteses externos são obrigatórios ao criar um alias de tipo para um tipo de tupla de struct.

type TupleAlias = string * float
type StructTupleAlias = (struct (string * float))

Interoperação com tuplas C#

Tuplas em C# são de struct e são equivalentes às tuplas de struct em F#. Se você precisar interoperar com C#, deverá usar tuplas de struct.

Isso é fácil de fazer. Por exemplo, imagine que você precisa passar uma tupla para uma classe de C# e consumir seu resultado, que também é uma tupla:

namespace CSharpTupleInterop
{
    public static class Example
    {
        public static (int, int) AddOneToXAndY((int x, int y) a) =>
            (a.x + 1, a.y + 1);
    }
}

Em seu código F#, você pode passar uma tupla de struct como o parâmetro e consumir o resultado como uma tupla de struct.

open TupleInterop

let struct (newX, newY) = Example.AddOneToXAndY(struct (1, 2))
// newX is now 2, and newY is now 3

Convertendo entre tuplas de referência e tuplas de struct

Como as tuplas de referência e as tuplas de struct têm uma representação subjacente completamente diferente, elas não são implicitamente conversíveis. Ou seja, o código a seguir não será compilado:

// Will not compile!
let (a, b) = struct (1, 2)

// Will not compile!
let struct (c, d) = (1, 2)

// Won't compile!
let f(t: struct(int*int)): int*int = t

Você deve fazer a correspondência de padrão em uma tupla e construir a outra com as partes constituintes. Por exemplo:

// Pattern match on the result.
let (a, b) = (1, 2)

// Construct a new tuple from the parts you pattern matched on.
let struct (c, d) = struct (a, b)

Forma compilada de tuplas de referência

Esta seção explica a forma das tuplas quando são compiladas. Não é necessário ler estas informações, a menos que você esteja visando o .NET Framework 3.5 ou anterior.

As tuplas são compiladas em objetos de um dos vários tipos genéricos, todos nomeados System.Tuple, sobrecarregados em arity, ou no número dos parâmetros de tipo. Os tipos de tupla aparecem nessa forma quando você os vê de outra linguagem, como C# ou Visual Basic, ou quando está usando uma ferramenta que não está ciente dos constructos de F#. Os tipos Tuple foram introduzidos no .NET Framework 4. Se você estiver visando uma versão anterior do .NET Framework, o compilador usará versões de System.Tuple da versão 2.0 da Biblioteca Principal de F#. Os tipos nesta biblioteca são usados apenas nos aplicativos que visam as versões 2.0, 3.0 e 3.5 do .NET Framework. O encaminhando de tipo é usado para garantir a compatibilidade entre os componentes F# do .NET Framework 2.0 e do .NET Framework 4.

Forma compilada das tuplas de struct

As tuplas de struct (por exemplo, struct (x, y)), são fundamentalmente diferentes das tuplas de referência. Elas são compiladas no tipo ValueTuple, sobrecarregado por arity, ou no número dos parâmetros de tipo. Elas são equivalentes às tuplas do C# e às tuplas do Visual Basic e interoperam bidirecionalmente.

Confira também