Fonctions comme arguments en Rust : 3 méthodes pour passer une fonction

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Fonction comme argument en Rust : du débutant au pro

\n\n

Avez-vous déjà écrit en Python ou JavaScript et passé facilement une fonction à une autre fonction ? Puis vous êtes passé à Rust et vous êtes heurté à un mur ? Ça vous parle. La question "How do you pass a Rust function as a parameter?" est l'une des plus populaires sur Stack Overflow. Et pour cause : le système de types et de possession de Rust ajoute plusieurs couches de complexité, mais ouvre aussi de nouvelles possibilités.

\n\n

Dans cet article, nous allons explorer trois approches principales : les pointeurs de fonction (fn), les closures et les traits. Vous apprendrez quand utiliser chaque méthode et cesserez de craindre le style fonctionnel en Rust.

\n\n

Pourquoi est-ce important ?

\n

Savoir passer des fonctions en paramètres n'est pas qu'une astuce académique. C'est la base pour :

\n
    \n
  • Créer des bibliothèques flexibles et réutilisables (ex : itérateurs, gestionnaires d'événements) ;
  • \n
  • Implémenter les patrons "Stratégie" et "Observateur" ;
  • \n
  • Écrire un code concis et expressif sans une multitude de if-else.
  • \n
\n

Contrairement aux langages dynamiques, Rust vérifie strictement les types et les durées de vie avec son compilateur. Vous devez donc comprendre clairement ce que vous passez : une simple adresse de fonction, une closure capturant le contexte, ou quelque chose de plus complexe.

\n\n

Approche 1 : Pointeur de fonction (Function Pointer) — fn

\n

La méthode la plus simple et directe. Si votre fonction ne capture pas de variables externes (elle est "pure"), vous pouvez utiliser le type fn. Attention : fn est un type, tandis que Fn, FnMut, FnOnce sont des traits. Ne les confondez pas !

\n\n
fn add_one(x: i32) -> i32 {\n    x + 1\n}\n\n// Fonction qui prend une autre fonction en paramètre\nfn apply_twice(f: fn(i32) -> i32, value: i32) -> i32 {\n    f(f(value))\n}\n\nfn main() {\n    let result = apply_twice(add_one, 5);\n    println!("Résultat : {}", result); // 7\n}
\n\n

Quand l'utiliser ? Quand la fonction est connue à la compilation, ne capture pas de variables et que vous n'avez pas besoin des performances des closures. Les pointeurs de fonction sont une abstraction zero-cost, sans allocation mémoire.

\n\n

Limitations de fn

\n

Le principal inconvénient : vous ne pouvez pas passer une closure qui capture des variables. Le code suivant ne compilera pas :

\n\n
fn main() {\n    let y = 10;\n    // La closure capture y\n    let closure = |x: i32| -> i32 { x + y };\n    // Erreur ! expected fn item, found closure\n    // let result = apply_twice(closure, 5);\n}
\n\n

Pour cela, il faut utiliser les traits Fn, FnMut, FnOnce.

\n\n

Approche 2 : Closures et traits Fn, FnMut, FnOnce

\n

Rust est un langage système, il doit donc savoir ce qui se passe avec la mémoire. Les closures peuvent capturer des variables de trois manières :

\n
    \n
  • Par référence (&T) — trait Fn. Peut être appelée autant de fois que voulu, sans modifier les données capturées.
  • \n
  • Par référence mutable (&mut T) — trait FnMut. Peut être appelée plusieurs fois, mais les données peuvent être modifiées.
  • \n
  • Par valeur (T) — trait FnOnce. Ne peut être appelée qu'une seule fois, après quoi la closure est "consommée".
  • \n
\n\n

Exemple avec Fn

\n
fn apply_twice_fn<F>(f: F, value: i32) -> i32\nwhere\n    F: Fn(i32) -> i32,\n{\n    f(f(value))\n}\n\nfn main() {\n    let y = 10;\n    let closure = |x| x + y; // capture y par référence\n    let result = apply_twice_fn(closure, 5);\n    println!("Fn : {}", result); // 25\n}
\n\n

Exemple avec FnMut

\n
fn apply_twice_mut<F>(mut f: F, value: i32) -> i32\nwhere\n    F: FnMut(i32) -> i32,\n{\n    f(f(value))\n}\n\nfn main() {\n    let mut counter = 0;\n    let mut closure = |x: i32| -> i32 {\n                

Blogs

Book Recommendations