Em Elixir, uma tupla é uma estrutura de dados que organiza dados, guardando um número fixo de itens de qualquer tipo, mas sem nomes explícitos para cada elemento. As tuplas são frequentemente usadas em Elixir para operações intensivas em leitura de memória, uma vez que o acesso de leitura a um elemento é uma operação de tempo constante. Normalmente não são usadas quando os elementos podem ter de ser adicionados ou removidos dinamicamente, porque, em vez de modificar a tupla existente, é criada uma nova tupla, o que exige que a memória seja alocada de antemão.
Na prática, as tuplas são criadas em Elixir com chavetas. Podes aceder individualmente aos elementos de uma tupla com a função elem/2, usando indexação a partir de 0:
empty_tuple = {}
one_element_tuple = {1}
multiple_element_tuple = {1, :a, "hello"}
elem(multiple_element_tuple, 2)
# => "hello"
As tuplas são frequentemente usadas na prática para representar informação agrupada.
Float.ratio(0.25)
# => {1, 4} indicating the numerator and denominator of the fraction ¼
A utilização de correspondência de padrões é dominante em código Elixir assertivo e idiomático. Talvez te lembres de que =/2 é descrito como um operador de correspondência e não como um operador de atribuição. Ao usar o operador de correspondência, se o padrão à esquerda corresponder ao padrão da direita, quaisquer variáveis à esquerda ficam ligadas, e o valor do lado direito é devolvido. É lançado um MatchError se não houver correspondência.
2 = 2
# => 2
# Literals can be matched if they are the same
2 = 3
# => ** (MatchError) no match of right hand side value: 3
{_, denominator} = Float.ratio(0.25)
# => {1, 4}
# the variable `denominator` is bound to the value 4
Lembra-te: as correspondências ocorrem do lado direito para o lado esquerdo.
No último exemplo, se não precisarmos de uma variável numa correspondência de padrões, podemos descartá-la referindo _. Qualquer variável que comece por _ não é acompanhada pelo runtime.
A correspondência de padrões também é uma ferramenta útil quando se criam várias cláusulas de função. A correspondência de padrões pode ser usada nos argumentos das funções, o que determina qual cláusula de função é invocada, começando no topo do ficheiro e descendo até à primeira correspondência. As variáveis podem ser ligadas numa cabeça de função e usadas no corpo da função.
defmodule Example do
def named_function(:a = variable_a) do
{variable_a, 1}
end
def named_function(:b = variable_b) do
{variable_b, 2}
end
end
Example.named_function(:a)
# => {:a, 1}
Example.named_function(:b)
# => {:b, 2}
Example.named_function(:c)
# => ** (FunctionClauseError) no function clause matching in Example.named_function/1
Enquanto te preparavas para fazer biscoitos para os teus amigos, descobriste que tens de converter algumas das medidas usadas na receita. Como só conheces o sistema métrico, precisas de arranjar uma forma de converter as medidas de pastelaria americanas mais comuns em mililitros (mL), para te facilitar a vida.
Usa esta tabela de conversão na tua solução:
| Unidade a converter | volume | em mililitros (mL) |
|---|---|---|
| mL | 1 | 1 |
| Chávena americana | 1 | 240 |
| Onça líquida americana | 1 | 30 |
| Colher de chá americana | 1 | 5 |
| Colher de sopa americana | 1 | 15 |
Como és um programador talentoso em formação, decides usar os mililitros como unidade de transição para facilitar a conversão de qualquer unidade da lista para qualquer outra (mesmo para ela própria).
Implementa a função KitchenCalculator.get_volume/1. Dado um tuplo de volume, deve devolver apenas a componente numérica.
KitchenCalculator.get_volume({:cup, 2.0})
# => 2.0
Implementa a função KitchenCalculator.to_milliliter/1. Dado um tuplo de volume, deve converter o volume em mililitros usando a tabela de conversão.
Usa várias cláusulas de função e correspondência de padrões para criar as funções para cada unidade. Os átomos usados para denotar cada unidade são: :cup, :fluid_ounce, :teaspoon, :tablespoon, :milliliter. Devolve o resultado da conversão envolvido num tuplo.
KitchenCalculator.to_milliliter({:cup, 2.5})
# => {:milliliter, 600.0}
Implementa a função KitchenCalculator.from_milliliter/2. Dado um tuplo de volume e a unidade pretendida, deve converter o volume para a unidade pretendida usando a tabela de conversão.
Usa várias cláusulas de função e correspondência de padrões para criar as funções para cada unidade. Os átomos usados para denotar cada unidade são: :cup, :fluid_ounce, :teaspoon, :tablespoon, :milliliter
KitchenCalculator.from_milliliter({:milliliter, 1320.0}, :cup)
# => {:cup, 5.5}
Implementa a função KitchenCalculator.convert/2. Dado um tuplo de volume e a unidade pretendida, deve converter o volume indicado para a unidade pretendida.
KitchenCalculator.convert({:teaspoon, 9.0}, :tablespoon)
# => {:tablespoon, 3.0}
Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.