Fonctions en Rust

Introduction aux fonctions

Les fonctions représentent des blocs de code réutilisables, permettant de répéter certaines opérations dans un script ou un programme. Elles sont essentielles pour structurer et organiser le code en Rust.

Syntaxe des fonctions

Pour déclarer une fonction en Rust, on utilise le mot-clé fn. Chaque programme en Rust doit comporter au moins une fonction : la fonction principale, souvent appelée main, qui constitue le point d'entrée de nombreux programmes.

fn main() {
    println!("hello, world!");
}

Nommage des fonctions

En Rust, on adopte la convention snake_case pour les noms de fonctions et de variables. Cela signifie que tous les caractères sont en minuscules et que les mots sont séparés par des underscores. Voici un exemple de définition de fonction :

fn main() {
    println!("hello, world!");
    une_autre_fonction();
}

fn une_autre_fonction() {
    println!("Ceci est une autre fonction");
}

Ce qui est intéressant, c'est que une_autre_fonction peut être définie avant ou après la fonction main. Rust ne se soucie pas de l'ordre, tant que la fonction est accessible dans le scope.

Paramètres des fonctions

Les fonctions peuvent accepter des paramètres, qui sont des variables spéciales intégrées à la signature de la fonction. Quand une fonction possède des paramètres, elle peut être appelée avec des valeurs concrètes. Dans cet exemple, la déclaration de une_autre_fonction inclut un paramètre x. Le type de x est noté comme étant i32. Il est nécessaire de spécifier le type de chaque paramètre dans la signature.`

fn main() {
    une_autre_fonction(5);
}

fn une_autre_fonction(x: i32) {
    println!("La valeur de x est : {x}");
}

Passage par valeur

Lorsqu'une méthode est appelée, une nouvelle zone de stockage est créée pour chaque paramètre de valeur. Les valeurs des paramètres réels sont ensuite copiées. Cela signifie que les modifications apportées au paramètre à l'intérieur de la fonction n'affectent pas l'argument original. Par exemple :

fn main() {
    let nombre: i32 = 5;
    rendre_zero(nombre);
    println!("La valeur de nombre est : {}", nombre);
}

fn rendre_zero(mut param_num: i32) {
    param_num = 0;
    println!("La valeur de param_num est : {}", param_num);
}

La sortie sera :

La valeur de param_num est : 0
La valeur de nombre est : 5

Remarque : Le mot-clé mut est utilisé pour indiquer que la valeur peut être modifiée à l'intérieur de la fonction.

Passage par référence

Lorsque des paramètres sont passés par référence, aucune nouvelle zone de stockage n'est créée. Les paramètres de référence pointent vers la même mémoire que les paramètres réels. Pour passer une valeur par référence, on utilise le préfixe &. Par exemple :

fn main() {
    let mut nombre: i32 = 5;
    rendre_zero(&mut nombre);
    println!("La valeur de nombre est : {}", nombre);
}

fn rendre_zero(param_num: &mut i32) {
    *param_num = 0;
    println!("La valeur de param_num est : {}", param_num);
}

La sortie sera :

La valeur de param_num est : 0
La valeur de nombre est : 0

Remarque : L'opérateur * est utilisé pour accéder à la valeur stockée à l'emplacement mémoire pointé par param_num, également appelé désérégation.

Fonctions avec valeurs de retour

Les fonctions peuvent renvoyer des valeurs au code qui les appelle. Leur type est annoté, comme pour les variables, et si une fonction retourne une valeur, le type de retour doit être spécifié après une flèche ->. La valeur de retour d'une fonction en Rust est déterminée par la dernière expression dans le bloc de la fonction. Voici un exemple d'une fonction avec une valeur de retour :

fn nombre() -> i32 {
    5
}

fn main() {
    let x = nombre();
    println!("La valeur de x est : {x}");
}

Dans cet exemple, nombre ne contient aucune nouvelle instruction, juste le nombre 5, et c'est tout à fait valide en Rust. Voici une autre illustration :

fn main() {
    let x = ajouter_un(5);
    println!("La valeur de x est : {x}");
}

fn ajouter_un(x: i32) -> i32 {
    x + 1
}

La sortie du code précédent sera "La valeur de x est : 6". Cependant, ajouter un point-virgule à la fin de la ligne avec x + 1 le transformera en instruction, entraînant une erreur ! Remarque : Les expressions ne doivent pas se terminer par un point-virgule.

Conclusion

Les fonctions constituent un aspect fondamental de la programmation en Rust, permettant de modulariser le code, de le rendre plus lisible, et d'encapsuler des comportements spécifiques.