Parcours
/
Crystal
Crystal
/
Exercices
/
Calculatrice de cuisine
Calculatrice de cuisine

Calculatrice de cuisine

Exercice d'apprentissage

Introduction

Un tuple est une liste ordonnée finie d'éléments, qui est immuable. Les tuples exigent que toutes les positions aient un type fixe. Cela signifie donc que le compilateur sait quel type se trouve à chaque position. Les types utilisés dans un tuple peuvent être différents à chaque position, mais ils doivent être connus à la compilation.

Crée un tuple

Selon que les types des valeurs du tuple peuvent être déduits à la compilation ou non, le tuple peut être créé de différentes manières. Si les valeurs sont connues à la compilation, le tuple peut être créé à l'aide de la syntaxe littérale de tuple ; sinon, elles doivent être déclarées explicitement. Il est également important que les types des valeurs correspondent aux types spécifiés dans le tuple et que le nombre de valeurs corresponde au nombre de types spécifiés. Voici un exemple de définition par la syntaxe littérale de tuple :

tuple = {1, "foo", 'c'} # Tuple(Int32, String, Char)

Il est également possible de créer un tuple à l'aide de la classe Tuple.

tuple = Tuple(Int32, String, Char).new(1, "foo", 'c')

Autrement, tu peux spécifier explicitement le type de la variable à laquelle le tuple est affecté.

tuple : Tuple(Int32, String, Char) = {1, "foo", 'c'}

Spécifier explicitement le type du tuple peut être utile, car cela permet de définir qu'une position doit contenir un type union. Cela signifie qu'une position peut contenir plusieurs types.

tuple : Tuple(Int32 | String, String, Char) = {1, "foo", 'c'}

Conversion

Crée un tuple à partir d'un tableau

Tu peux créer un tuple à partir d'un tableau à l'aide de la méthode from de la classe Tuple. Cela exige que le type du tuple soit spécifié.

array = [1, "foo", 'c']
tuple = Tuple(Int32, String, Char).from(array)

Conversion en tableau

Tu peux convertir un tuple en tableau à l'aide de la méthode to_a. Le type des éléments du tableau obtenu est l'union des types de chaque champ du tuple.

tuple = {1, "foo", 'c'}
array = tuple.to_a
array # => [1, "foo", 'c']

Accède aux éléments

Comme les tableaux, les tuples sont indexés à partir de zéro, ce qui signifie que le premier élément se trouve à l'indice 0. Cependant, contrairement aux tableaux, le type de chaque élément est fixe et connu à la compilation ; par conséquent, lorsqu'on indexe un tuple, le type de l'élément est propre à la position. Pour accéder à un élément d'un tuple, tu peux utiliser l'opérateur [].

array = [1, "foo", 'c']
array[0]         # => 1
typeof(array[0]) # => Int32 | String | Char

tuple = {1, "foo", 'c'}
tuple[0]         # => 1
typeof(tuple[0]) # => Int32

Une autre différence dans l'accès aux éléments d'un tuple par rapport aux tableaux est que, si l'indice est précisé, le compilateur vérifie que cet indice se situe dans les limites du tuple. Cela signifie que tu obtiendras une erreur à la compilation plutôt qu'une erreur à l'exécution.

tuple = {1, "foo", 'c'}
tuple[3]
# => Error: index out of bounds for Tuple(Int32, String, Char) (3 not in -3..2)

Cependant, si l'indice est stocké dans une variable, le compilateur ne pourra pas vérifier à la compilation que cet indice se situe dans les limites du tuple et produira à la place une erreur à l'exécution.

Sous-tuple

Tu peux obtenir un sous-tuple d'un tuple en utilisant l'opérateur [] avec un intervalle. Ce qui est renvoyé est un nouveau tuple contenant les éléments de l'intervalle spécifié. L'intervalle doit être fourni à la compilation ; sinon, le compilateur ne pourra pas connaître les types des éléments du sous-tuple. Cela signifie que l'intervalle doit être un littéral d'intervalle et non être affecté à une variable.

tuple = {1, "foo", 'c'}
subtuple = tuple[0..1] # Tuple(Int32, String)

i = 0..1
tuple[i]
# Error: Tuple#[](Range) can only be called with range literals known at compile-time

Quand utiliser un tuple

Les tuples sont utiles lorsque tu veux regrouper un nombre fixe de valeurs dont les types sont connus à la compilation. En effet, les tuples consomment moins de mémoire et sont plus rapides que les tableaux en raison de leur immuabilité. Un autre cas d'usage consiste à renvoyer plusieurs valeurs depuis une méthode. C'est particulièrement utile si les valeurs ont des types différents, puisque chaque position du tuple peut avoir un type différent.

Les tuples ne doivent pas être utilisés lorsqu'on a besoin d'une structure de données qui peut grandir ou rétrécir, ou qui doit être modifiée souvent.

Les symboles sont des identifiants nommés qui peuvent servir à faire référence à une valeur. Les symboles sont créés à l'aide d'un littéral de symbole, c'est-à-dire en faisant précéder un nom du caractère :, par exemple :foo. Ils peuvent aussi être écrits entre guillemets, par exemple :"foo", ce qui permet, par exemple, d'inclure des espaces dans le nom.

:foo           # => :foo
:"foo boo"     # => :"foo boo"
:foo == :"foo" # => true

Les symboles sont utilisés à de nombreux endroits dans le langage, notamment comme clés dans les namedtuples et pour représenter des noms de méthodes et de variables.

Les symboles en Crystal

Les symboles en Crystal sont assez différents de ceux de Ruby. En Crystal, un symbole est une sorte de constante et il est donc affecté à la compilation. Cela signifie que les symboles ne peuvent pas être créés dynamiquement, ce qui est possible en Ruby.

En Crystal, les symboles sont représentés par des Int32, ce qui les rend très efficaces.

Conversion

Les symboles peuvent être convertis en chaînes de caractères, mais pas l'inverse. En effet, les symboles sont créés à la compilation, alors que les chaînes de caractères sont créées à l'exécution.

:foo.to_s # => "foo"

Instructions

Alors que tu t'apprêtes à faire des cookies pour tes amis, tu t'aperçois que tu dois convertir certaines des mesures utilisées dans la recette. Comme tu ne connais que le système métrique, tu dois trouver un moyen de convertir les mesures de cuisine américaines courantes en millilitres (mL) pour te simplifier la tâche.

Utilise ce tableau de conversion pour ta solution :

Unité à convertir volume en millilitres (mL)
mL 1 1
Tasse américaine 1 240
Once liquide américaine 1 30
Cuillère à café américaine 1 5
Cuillère à soupe américaine 1 15

Programmeur talentueux en formation, tu décides d'utiliser les millilitres comme unité intermédiaire pour faciliter la conversion de n'importe quelle unité de la liste vers n'importe quelle autre (y compris elle-même).

1. Récupère la composante numérique d'une paire de volumes

Implémente la méthode KitchenCalculator.get_volume. Étant donné un tuple représentant une paire de volumes, elle doit renvoyer uniquement la composante numérique.

KitchenCalculator.get_volume({:cup, 2.0})
# => 2.0

2. Convertis la paire de volumes en millilitres

Implémente la méthode KitchenCalculator.to_milliliter. Étant donné un tuple représentant une paire de volumes, elle doit convertir le volume en millilitres à l'aide du tableau de conversion.

KitchenCalculator.to_milliliter({:cup, 2.5})
# => {:milliliter, 600.0}

3. Convertis la paire de volumes en millilitres vers une autre unité

Implémente la méthode KitchenCalculator.from_milliliter. Étant donné un tuple représentant une paire de volumes et l'unité souhaitée, elle doit convertir le volume vers l'unité souhaitée à l'aide du tableau de conversion.

KitchenCalculator.from_milliliter({:milliliter, 1320.0}, :cup)
# => {:cup, 5.5}

4. Convertis d'une unité vers n'importe quelle autre unité

Implémente la méthode KitchenCalculator.convert. Étant donné un tuple représentant une paire de volumes et l'unité souhaitée, elle doit convertir le volume donné vers l'unité souhaitée.

KitchenCalculator.convert({:teaspoon, 9.0}, :tablespoon)
# => {:tablespoon, 3.0}
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Crystal Exercism

Prêt à commencer Calculatrice de cuisine ?

Inscris-toi sur Exercism pour apprendre et maîtriser Crystal avec 26 concepts142 exercices, et un vrai mentorat humain, le tout gratuitement.