Percursos
/
Elixir
Elixir
/
Exercícios
/
Calculadora de Cozinha
Calculadora de Cozinha

Calculadora de Cozinha

Exercício de aprendizagem

Introdução

Tuplas

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"

Tuplas como informação agrupada

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 ¼

Correspondência de padrões

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.

Correspondência de padrões em funções nomeadas

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

Instruções

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).

1. Obtém a componente numérica de um tuplo de volume

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

2. Converte o tuplo de volume em mililitros

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}

3. Converte o tuplo de volume em mililitros para outra unidade

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}

4. Converte de qualquer unidade para qualquer unidade

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}
Editar via GitHub A ligação abre numa nova janela ou separador
Elixir Exercism

Estás pronto para começar Calculadora de Cozinha?

Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.