Aller au contenu

Les variables en Rust

Une variable, c’est simplement un nom que vous donnez à une valeur pour pouvoir l’utiliser plus tard. Imaginez une boîte avec une étiquette : vous mettez quelque chose dedans, vous écrivez un nom dessus, et vous y faites référence par ce nom au lieu de répéter la valeur partout.

En Rust, on crée une variable avec le mot-clé let :

fn main() {
let age = 30;
println!("J'ai {age} ans");
}

Sortie :

J'ai 30 ans
▶ Essayez par vous-même

Décortiquons cette ligne :

  • let : dit à Rust « je crée une nouvelle variable ».
  • age : le nom que nous avons choisi.
  • = : affecte la valeur de droite au nom de gauche.
  • 30 : la valeur que nous stockons.

Le {age} dans println! affiche la valeur de la variable. C’est ce qu’on appelle l’interpolation de chaîne : Rust remplace {age} par ce que contient age.

En Rust, chaque valeur a un type (un nombre entier, du texte, true/false, etc.). Vous pourriez vous attendre à devoir déclarer ce type, mais en général ce n’est pas nécessaire : Rust regarde la valeur et le déduit tout seul. C’est ce qu’on appelle l’inférence de type.

fn main() {
let score = 95; // Rust déduit que c'est un entier
let name = "Ferris"; // Rust déduit que c'est du texte
let is_active = true; // Rust déduit que c'est un booléen
println!("{name} : {score}, actif = {is_active}");
}

Sortie :

Ferris : 95, actif = true
▶ Essayez par vous-même

Si vous voulez être explicite, vous pouvez écrire le type après deux-points :

let score: i32 = 95; // i32 = un entier sur 32 bits

Voici ce qui surprend les personnes qui viennent d’autres langages : en Rust, une fois qu’une variable a reçu une valeur, vous ne pouvez pas la modifier, par défaut. « Immuable » veut simplement dire qui ne peut pas être modifié.

Ce code ne compile pas :

fn main() {
let count = 1;
count = 2; // ❌ erreur : impossible d'affecter deux fois une variable immuable
println!("{count}");
}

Le compilateur vous arrête avec un message clair :

error[E0384]: cannot assign twice to immutable variable `count`

Autrement dit (rustc s’exprime toujours en anglais) : impossible d’affecter deux fois une valeur à la variable immuable count.

Pourquoi un langage ferait-il cela exprès ? Parce que beaucoup de bugs viennent de valeurs qui changent au moment où on ne s’y attend pas. En rendant les choses non modifiables, sauf si vous demandez à pouvoir les changer, Rust rend votre code plus prévisible. C’est une fonctionnalité, pas une limitation.

Quand vous avez vraiment besoin qu’une valeur change, ajoutez le mot-clé mut (abréviation de mutable, c’est-à-dire modifiable) :

fn main() {
let mut count = 1;
println!("Avant : {count}");
count = 2; // ✅ autorisé maintenant, grâce à `mut`
println!("Après : {count}");
}

Sortie :

Avant : 1
Après : 2
▶ Essayez par vous-même

Rust vous permet de déclarer une nouvelle variable avec le même nom qu’une ancienne. C’est ce qu’on appelle le shadowing (masquage) : la nouvelle variable « fait de l’ombre » à l’ancienne :

fn main() {
let x = 5;
let x = x + 1; // un nouveau x, calculé à partir de l'ancien -> 6
let x = x * 2; // encore un nouveau x -> 12
println!("x vaut {x}");
}

Sortie :

x vaut 12
▶ Essayez par vous-même

Cela ressemble à mut, mais c’est différent :

  • mut modifie la valeur de la même variable.
  • Le shadowing crée une variable toute nouvelle qui se trouve réutiliser le nom, et elle peut même avoir un type différent.

Le shadowing est pratique quand vous voulez transformer une valeur tout en gardant le même nom :

fn main() {
let spaces = " "; // du texte
let spaces = spaces.len(); // maintenant un nombre (combien d'espaces)
println!("Nombre d'espaces : {spaces}");
}

Sortie :

Nombre d'espaces : 3
▶ Essayez par vous-même

Une constante est une valeur qui ne change jamais et qui est fixée à la compilation. On la déclare avec const au lieu de let, et il faut écrire son type :

const MAX_SCORE: u32 = 100;
fn main() {
println!("Le score maximum est {MAX_SCORE}");
}

Sortie :

Le score maximum est 100
▶ Essayez par vous-même

Par convention, les constantes s’écrivent en UPPER_SNAKE_CASE (majuscules séparées par des tirets bas). Voici comment elles se comparent aux variables ordinaires :

Variable let Constante const
Modifiable ? Seulement avec mut Jamais
Type obligatoire ? Facultatif (déduit) Obligatoire
Style de nom snake_case UPPER_SNAKE_CASE
Où l’utiliser Dans les fonctions Partout, même hors des fonctions

Utilisez une constante pour les valeurs vraiment fixes, comme le nombre de secondes dans une minute ou une limite maximale.

  • Utilisez le snake_case : des mots en minuscules reliés par des tirets bas, comme user_name ou total_price.
  • Un nom peut contenir des lettres, des chiffres et des tirets bas, mais ne peut pas commencer par un chiffre.
  • Choisissez des noms parlants : age vaut mieux que a.

Créez une variable level qui commence à 1. Affichez-la, augmentez-la de 1 deux fois et affichez-la après chaque changement, pour obtenir Niveau 1, Niveau 2, Niveau 3. Indice : une valeur qui change a besoin de mut, et level = level + 1; ajoute un.

Voir la solution
fn main() {
let mut level = 1;
println!("Niveau {level}");
level = level + 1;
println!("Niveau {level}");
level = level + 1;
println!("Niveau {level}");
}

Sortie :

Niveau 1
Niveau 2
Niveau 3
▶ Essayez par vous-même

Déclarez une constante SECONDS_PER_MINUTE égale à 60. Commencez par let time = 5; (en minutes), puis faites du shadowing sur time pour qu’elle contienne la même durée en secondes, et affichez Cela fait 300 secondes. Indice : le nouveau time peut être construit à partir de l’ancien : let time = time * ...;.

Voir la solution
const SECONDS_PER_MINUTE: u32 = 60;
fn main() {
let time = 5; // minutes
let time = time * SECONDS_PER_MINUTE; // un nouveau `time`, maintenant en secondes
println!("Cela fait {time} secondes");
}

Sortie :

Cela fait 300 secondes
▶ Essayez par vous-même

Pas besoin de mut : le second let crée une toute nouvelle variable qui réutilise le nom. Rust déduit aussi ici que time est un u32, parce qu’elle est multipliée par la constante de type u32.

  • On crée des variables avec let ; en général, Rust déduit le type pour vous.
  • Les variables sont immuables par défaut : ajoutez mut pour autoriser les modifications.
  • Le shadowing redéclare un nom avec let, ce qui crée une nouvelle variable (qui peut changer de type).
  • Les constantes (const) ne changent jamais, ont toujours besoin d’un type et s’écrivent en UPPER_SNAKE_CASE.

Petit quiz

1. Par défaut, peut-on réaffecter une variable let en Rust ?

2. Qu’est-ce que le shadowing en Rust ?

3. D’après cette page, quelle convention de nommage utilisent les variables Rust ?

Score : 0 / 3