In Elixir, una tupla è una struttura dati che organizza i dati e che contiene un numero fisso di elementi di qualsiasi tipo, ma senza nomi espliciti per ciascun elemento. Le tuple in Elixir sono spesso usate per operazioni che richiedono molte letture in memoria, dato che l'accesso in lettura a un elemento è un'operazione a tempo costante. Di solito non si usano quando gli elementi potrebbero dover essere aggiunti o rimossi dinamicamente, perché invece di modificare la tupla esistente se ne crea una nuova, il che richiede di allocare memoria in anticipo.
In pratica, in Elixir le tuple si creano usando le parentesi graffe. Si può accedere singolarmente agli elementi di una tupla con la funzione elem/2, usando indici che partono da 0:
empty_tuple = {}
one_element_tuple = {1}
multiple_element_tuple = {1, :a, "hello"}
elem(multiple_element_tuple, 2)
# => "hello"
In pratica, le tuple sono spesso usate per rappresentare informazioni raggruppate.
Float.ratio(0.25)
# => {1, 4} indicating the numerator and denominator of the fraction ¼
L'uso del pattern matching è dominante nel codice Elixir idiomatico e assertivo. Forse ricorderai che =/2 viene descritto come un operatore di match invece che come un operatore di assegnazione. Quando si usa l'operatore di match, se il pattern a sinistra corrisponde a quello a destra, le variabili a sinistra vengono legate e viene restituito il valore del lato destro. Se non c'è corrispondenza, viene sollevato un MatchError.
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
Ricorda: le corrispondenze avvengono dal lato destro verso il lato sinistro.
Nell'ultimo esempio, se in un pattern match non ci serve una variabile, possiamo scartarla facendo riferimento a _. Qualsiasi variabile che inizia con un _ non viene tracciata dal runtime.
Il pattern matching è anche uno strumento utile quando si creano più clausole di funzione. Il pattern matching si può usare sugli argomenti della funzione, e questo determina quale clausola di funzione chiamare, partendo dall'alto del file e scendendo fino alla prima corrispondenza. Le variabili si possono legare nella testa della funzione e usare nel corpo della funzione.
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
Mentre ti prepari a cuocere dei biscotti per i tuoi amici, ti rendi conto di dover convertire alcune delle misure usate nella ricetta. Conoscendo soltanto il sistema metrico decimale, devi trovare un modo per convertire le comuni misure di cucina statunitensi in millilitri (mL) per tua comodità.
Usa questa tabella di conversione per la soluzione:
| Unità da convertire | volume | in millilitri (mL) |
|---|---|---|
| mL | 1 | 1 |
| tazza americana | 1 | 240 |
| oncia liquida americana | 1 | 30 |
| cucchiaino americano | 1 | 5 |
| cucchiaio americano | 1 | 15 |
Dato che sei un programmatore di talento in formazione, decidi di usare i millilitri come unità di transizione per facilitare la conversione da qualsiasi unità elencata a qualsiasi altra (anche a se stessa).
Implementa la funzione KitchenCalculator.get_volume/1. Data una tupla coppia di volume, deve restituire solo la componente numerica.
KitchenCalculator.get_volume({:cup, 2.0})
# => 2.0
Implementa la funzione KitchenCalculator.to_milliliter/1. Data una tupla coppia di volume, deve convertire il volume in millilitri usando la tabella di conversione.
Usa più clausole di funzione e il pattern matching per creare le funzioni per ogni unità. Gli atom usati per indicare ciascuna unità sono: :cup, :fluid_ounce, :teaspoon, :tablespoon, :milliliter. Restituisci il risultato della conversione racchiuso in una tupla.
KitchenCalculator.to_milliliter({:cup, 2.5})
# => {:milliliter, 600.0}
Implementa la funzione KitchenCalculator.from_milliliter/2. Data una tupla coppia di volume e l'unità desiderata, deve convertire il volume nell'unità desiderata usando la tabella di conversione.
Usa più clausole di funzione e il pattern matching per creare le funzioni per ogni unità. Gli atom usati per indicare ciascuna unità sono: :cup, :fluid_ounce, :teaspoon, :tablespoon, :milliliter
KitchenCalculator.from_milliliter({:milliliter, 1320.0}, :cup)
# => {:cup, 5.5}
Implementa la funzione KitchenCalculator.convert/2. Data una tupla coppia di volume e l'unità desiderata, deve convertire il volume dato nell'unità desiderata.
KitchenCalculator.convert({:teaspoon, 9.0}, :tablespoon)
# => {:tablespoon, 3.0}
Iscriviti a Exercism per imparare e padroneggiare Elixir con 58 concetti168 esercizi e il mentoring di persone reali, tutto gratis.