Como usar o Módulo Tuple em Elixir?
Tags: elixir
Published: 2020-11-03 14:34:15

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mcspuyxxg1iazopn4hsl.jpg)

*Texto anterior: [Como começar a aprender a linguagem de programação Elixir?](https://dev.to/elixir_utfpr/como-comecar-a-aprender-a-linguagem-de-programacao-elixir-26o5)*

Todos que conhecem Elixir devem conhecer a [tupla](https://elixirschool.com/pt/lessons/basics/collections/#tuplas), uma estrutura de dados que permite você juntar valores de diferentes tipos, sejam estes valores de tipos [básicos](https://elixirschool.com/pt/lessons/basics/basics/#tipos-b%C3%A1sicos) ou não básicos. 

Para criar uma tupla, basta abrir uma chave "{", listar os valores separados por vírgulas, e fechar a chave "}".

Exemplos:
```elixir
{"Adolfo", "UTFPR", 2008}
{:idade, 25, :peso, 60.5}
{true, [:p, :implies, :q]} 
```

Não gosto muito da definição da [Elixir School](https://elixirschool.com/pt/lessons/basics/collections/#tuplas) nem da [definição do site da linguagem](https://elixir-lang.org/getting-started/basic-types.html#tuples), então vou dar a definição do [Dave Thomas em Programming Elixir](http://bit.ly/PragProgDave): tuplas são coleções ordenadas de valores. Ele reforça que "como todas as estruturas de dados em Elixir, uma vez criada uma tupla não pode ser modificada".

Qual é a forma mais comum de obter valores de tuplas? Fazendo casamento de padrões. No exemplo abaixo, se sabemos que a tupla contém quatro valores, dos quais o primeiro e o terceiro são os átomos :idade e :peso, e o segundo e o quarto são a idade e o peso da pessoa, podemos fazer assim para obter idade e peso:
```elixir
iex> pessoa = {:idade, 25, :peso, 60.5}
{:idade, 25, :peso, 60.5}
iex> {:idade, idade, :peso, peso} = pessoa
{:idade, 25, :peso, 60.5}
iex> idade
25
iex> peso
60.5

```

OK, então onde entra o [módulo Tuple](https://hexdocs.pm/elixir/Tuple.html) e o que podemos fazer com ele?
Segundo a documentação, no módulo Tuple você tem "Funções para trabalhar com tuplas." Meio óbvio, né?

Eu confesso que nem sabia da existência deste módulo até alguém perguntar por tuplas no [Discord da Groxio Learning](http://bit.ly/DiscordGroxioLearning):
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mcwtia1l1m56rwybict4.png)

A própria documentação do módulo avisa: "As funções neste módulo que adicionam e removem elementos de tuplas raramente são usadas na prática, pois geralmente implicam que tuplas estão sendo usadas como coleções."

O módulo Tuple (na versão 1.11.1 de Elixir) tem apenas 5 funções:
- append(tupla, valor):
Insere um elemento no fim de uma tupla.
- delete_at(tupla, índice): 
Remove um elemmento de uma tupla.
- duplicate(dado, tamanho): 
Cria uma nova tupla.
- insert_at(tupla, índice, valor): 
Insere um elemento em uma tupla.
- to_list(tupla): 
Converte uma tupla em uma lista.

Abaixo algumas interações na iex do Elixir usando as funções acima:
```elixir
iex> pessoa = {:idade, 25, :peso, 60.5}
{:idade, 25, :peso, 60.5}
iex> Tuple.append(pessoa, "João")
{:idade, 25, :peso, 60.5, "João"}
iex> Tuple.delete_at(pessoa, 3)
{:idade, 25, :peso}
iex> Tuple.duplicate(:elixir, 5)
{:elixir, :elixir, :elixir, :elixir, :elixir}
iex> Tuple.insert_at(pessoa, 4, "João")
{:idade, 25, :peso, 60.5, "João"}
iex> Tuple.insert_at(pessoa, 3, "João")
{:idade, 25, :peso, "João", 60.5}
iex> Tuple.to_list(pessoa)
[:idade, 25, :peso, 60.5]
```

Como você pode ver acima, o primeiro elemento de uma tupla tem índice 0.

Vocês também podem usar, como tuplas, três funções que não são do módulo Tuple: 
- tuple_size(tupla): retorna o tamanho de uma tupla.
- elem(tupla, índice): retorna o elemento na posição índice da tupla.
- put_elem(tupla, índice, valor): coloca o valor na posição dada por índice na tupla.

Exemplos:
```elixir
iex> pessoa = {:idade, 25, :peso, 60.5}
{:idade, 25, :peso, 60.5}
iex> tuple_size(pessoa)
4
iex> elem(pessoa,1)
25
iex> elem(pessoa,0)
:idade
iex> put_elem(pessoa,0, "oi")
{"oi", 25, :peso, 60.5}
```
 
Na página da linguagem há uma [discussão um pouco mais avançada sobre a diferença entre listas e tuplas](https://elixir-lang.org/getting-started/basic-types.html#lists-or-tuples).

Portanto, o conselho é: usem tuplas mas evitem usar o módulo Tuple.