<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rust :: Ma documentation</title><link>https://quentinpigne.github.io/developpement/rust/index.html</link><description>Bases du langage Contrôle de flux et expressions Ownership et emprunt Structures, énumérations et méthodes Déstructuration et patterns Les traits Les closures Le mécanisme Deref Le type Option Result et la gestion des erreurs Les itérateurs</description><generator>Hugo</generator><language>fr-FR</language><atom:link href="https://quentinpigne.github.io/developpement/rust/index.xml" rel="self" type="application/rss+xml"/><item><title>Bases du langage</title><link>https://quentinpigne.github.io/developpement/rust/basics/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/basics/index.html</guid><description>Présentation Rust est un langage de programmation compilé, à typage statique fort, créé par Graydon Hoare chez Mozilla et dont la première version stable (1.0) est sortie en 2015. Il est aujourd’hui maintenu par la Rust Foundation.
Son objectif principal est d’offrir les performances du C et du C++ tout en garantissant la sûreté mémoire à la compilation, sans ramasse-miettes (garbage collector).</description></item><item><title>Contrôle de flux et expressions</title><link>https://quentinpigne.github.io/developpement/rust/control-flow/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/control-flow/index.html</guid><description>Rust est un langage orienté expression : la plupart de ses constructions de contrôle produisent une valeur au lieu de se contenter de piloter l’exécution. Comprendre ce principe, et le type ! qui le rend cohérent, explique une bonne partie de la syntaxe idiomatique.
Presque tout est une expression Rust distingue :
les instructions (statements), qui ne produisent pas de valeur et se terminent par un point-virgule ; les expressions, qui en produisent une. Un bloc { } est lui-même une expression : sa valeur est celle de sa dernière expression, écrite sans point-virgule.</description></item><item><title>Ownership et emprunt</title><link>https://quentinpigne.github.io/developpement/rust/ownership/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/ownership/index.html</guid><description>Le sujet central de Rust. L’objectif ici est de te donner un modèle mental clair plutôt qu’une liste de règles.
La règle fondamentale : un seul propriétaire En Rust, chaque valeur a exactement un propriétaire à la fois. Quand le propriétaire sort de portée, la valeur est libérée (mémoire désallouée). C’est ça qui remplace le garbage collector.</description></item><item><title>Structures, énumérations et méthodes</title><link>https://quentinpigne.github.io/developpement/rust/structs-enums/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/structs-enums/index.html</guid><description>Rust n’a pas de classes. La modélisation des données repose sur deux constructions — les structures et les énumérations — auxquelles on attache des comportements via des blocs impl. L’héritage n’existe pas ; le partage de comportement passe par les traits.
Les structures Trois formes existent, selon que les champs sont nommés, anonymes, ou absents.
// Structure classique : champs nommés struct Utilisateur { nom: String, courriel: String, actif: bool, connexions: u64, } // Structure tuple : champs anonymes, accessibles par index struct Point(f64, f64); struct Metres(f64); // Structure unité : aucun champ struct Marqueur; La structure tuple sert principalement à créer un type distinct autour d’une valeur existante — ce que l’on appelle le patron newtype. Metres(f64) et Secondes(f64) ne sont alors pas interchangeables, alors que deux f64 le seraient.</description></item><item><title>Déstructuration et patterns</title><link>https://quentinpigne.github.io/developpement/rust/destructuring/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/destructuring/index.html</guid><description>En Rust, la déstructuration n’est pas réservée au match : elle est disponible partout où le langage attend un motif (pattern), y compris dans les paramètres de fonction. C’est ce mécanisme qui explique des syntaxes déroutantes au premier abord, comme les extracteurs du framework web Axum.
Un motif, pas seulement un nom de variable N’importe quel paramètre de fonction peut utiliser un motif, et pas uniquement un identifiant. La partie à gauche du : est un motif, celle de droite un type.</description></item><item><title>Les traits</title><link>https://quentinpigne.github.io/developpement/rust/traits/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/traits/index.html</guid><description>Un trait décrit un comportement qu’un type peut fournir. C’est le mécanisme d’abstraction central de Rust : il remplace à la fois les interfaces, les classes abstraites et la surcharge d’opérateurs des langages à objets, et il sous-tend la quasi-totalité de la bibliothèque standard — Iterator, Display, Clone, Deref, From sont tous des traits.
Déclarer et implémenter trait Surface { fn aire(&amp;self) -&gt; f64; } struct Cercle { rayon: f64 } struct Rectangle { largeur: f64, hauteur: f64 } impl Surface for Cercle { fn aire(&amp;self) -&gt; f64 { std::f64::consts::PI * self.rayon * self.rayon } } impl Surface for Rectangle { fn aire(&amp;self) -&gt; f64 { self.largeur * self.hauteur } } Le trait déclare la signature, chaque impl ... for ... fournit le corps. La différence essentielle avec une interface classique : le trait et le type sont indépendants. Il est possible d’implémenter son propre trait sur un type de la bibliothèque standard.</description></item><item><title>Les closures</title><link>https://quentinpigne.github.io/developpement/rust/closures/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/closures/index.html</guid><description>Une closure est une fonction anonyme capable de capturer son environnement. C’est la brique de base des chaînes d’itérateurs et des combinateurs d’Option — map, filter, unwrap_or_else en prennent tous une. La particularité de Rust tient à ce que cette capture doit se concilier avec les règles de propriété, ce qui donne naissance à trois traits distincts.
Syntaxe let ajouter = |a: i32, b: i32| -&gt; i32 { a + b }; let ajouter = |a, b| a + b; // Types inférés, corps en expression unique assert_eq!(ajouter(2, 3), 5); Contrairement aux fonctions, les annotations de type sont facultatives : le compilateur les déduit du contexte d’utilisation.</description></item><item><title>Le mécanisme Deref</title><link>https://quentinpigne.github.io/developpement/rust/deref/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/deref/index.html</guid><description>Le problème résolu Certaines conversions semblent fonctionner « sans raison apparente » :
fn afficher(s: &amp;str) { println!("{s}"); } let possedee = String::from("Hello"); afficher(&amp;possedee); // Compile, alors que &amp;possedee est de type &amp;String &amp;possedee est un &amp;String, pas un &amp;str. En toute logique, le code ne devrait pas compiler. C’est le trait Deref qui fait le travail en coulisses.</description></item><item><title>Le type Option</title><link>https://quentinpigne.github.io/developpement/rust/option/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/option/index.html</guid><description>Rust ne possède ni null ni undefined. L’absence de valeur est représentée par un type à part entière, Option&lt;T&gt;, que le compilateur oblige à traiter. Cette page recense les usages idiomatiques du type.
Choisir le bon outil Situation Pattern Exemple Transformer la valeur si elle est présente map opt.map(|s| s.len()) Transformer en produisant un autre Option and_then opt.and_then(|s| s.parse().ok()) Ne garder que si un prédicat est vérifié filter opt.filter(|s| !s.is_empty()) Fournir une valeur par défaut unwrap_or_else, unwrap_or_default opt.unwrap_or_default() Sortie anticipée puis code linéaire let ... else let Some(x) = opt else { return; }; Propager l’absence à l’appelant ? let x = opt?; L’absence est une erreur pour l’appelant ok_or_else opt.ok_or_else(|| Erreur::Absent)? Un seul cas intéresse, avec effet de bord if let if let Some(x) = opt { ... } Les deux branches font un vrai travail match voir plus bas Test booléen is_some_and, is_none_or opt.is_some_and(|x| x &gt; 3) Tip Règle empirique : si un match comporte une branche None =&gt; None ou None =&gt; valeur_constante, c’est un combinateur déguisé. Il gagne à être réécrit.</description></item><item><title>Result et la gestion des erreurs</title><link>https://quentinpigne.github.io/developpement/rust/result/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/result/index.html</guid><description>Rust n’a pas d’exceptions. Une opération susceptible d’échouer renvoie un Result&lt;T, E&gt;, que le compilateur oblige à traiter. Cette page traite du versant « échec » ; l’absence de valeur, elle, relève d’Option.
Le type enum Result&lt;T, E&gt; { Ok(T), Err(E), } Comme Option, c’est une simple énumération de la bibliothèque standard, annotée #[must_use] : ignorer un Result déclenche un avertissement.</description></item><item><title>Les itérateurs</title><link>https://quentinpigne.github.io/developpement/rust/iterators/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://quentinpigne.github.io/developpement/rust/iterators/index.html</guid><description>Les trois méthodes de parcours Méthode Type de l’Item Effet sur la collection iter() &amp;T Empruntée en lecture, réutilisable ensuite iter_mut() &amp;mut T Empruntée en écriture, réutilisable ensuite into_iter() T Consommée, si le receveur est possédé La nuance qui échappe le plus souvent : into_iter() est polymorphe sur son receveur.
let mut v: Vec&lt;String&gt; = vec!["a".into(), "b".into()]; v.into_iter() // Item = String (v est consommé) (&amp;v).into_iter() // Item = &amp;String (équivaut à v.iter()) (&amp;mut v).into_iter() // Item = &amp;mut String (équivaut à v.iter_mut()) Il existe en effet trois implémentations distinctes de IntoIterator : une pour Vec&lt;T&gt;, une pour &amp;Vec&lt;T&gt; et une pour &amp;mut Vec&lt;T&gt;. C’est ce qui fait fonctionner for x in &amp;v.</description></item></channel></rss>