Podcast
Questions and Answers
Quelle est la signification de mut
dans la déclaration d'une variable en Rust?
Quelle est la signification de mut
dans la déclaration d'une variable en Rust?
- Indique que la variable est immutable et ne peut pas être modifiée après son initialisation.
- Spécifie que la variable doit être stockée sur le tas (heap) au lieu de la pile (stack).
- Indique que la variable est mutable et peut être modifiée après son initialisation. (correct)
- Définit la portée de la variable comme étant globale.
Lequel des types de données suivants n'est pas un type entier signé valide en Rust?
Lequel des types de données suivants n'est pas un type entier signé valide en Rust?
- `i64`
- `i128`
- `u64` (correct)
- `isize`
Quelle est la largeur en bits du type bool
en Rust?
Quelle est la largeur en bits du type bool
en Rust?
- 32 bits
- Dépend de l'architecture du processeur
- 16 bits
- 8 bits (correct)
Lorsque l'inférence de type est utilisée en Rust, comment le compilateur détermine-t-il le type d'une variable?
Lorsque l'inférence de type est utilisée en Rust, comment le compilateur détermine-t-il le type d'une variable?
Qu'est-ce qu'un bloc en Rust?
Qu'est-ce qu'un bloc en Rust?
Quelle est la valeur d'un bloc en Rust s'il se termine par un point-virgule (;
)?
Quelle est la valeur d'un bloc en Rust s'il se termine par un point-virgule (;
)?
Quelle est la principale différence entre let
et const
lors de la déclaration de variables en Rust?
Quelle est la principale différence entre let
et const
lors de la déclaration de variables en Rust?
Dans quel but peut-on déclarer une variable static
dans Rust?
Dans quel but peut-on déclarer une variable static
dans Rust?
Quelle est la fonctionnalité de l'opérateur if let
en Rust?
Quelle est la fonctionnalité de l'opérateur if let
en Rust?
Comment fonctionne l'instruction match
en Rust par rapport à un switch
dans d'autres langages de programmation?
Comment fonctionne l'instruction match
en Rust par rapport à un switch
dans d'autres langages de programmation?
Dans une boucle for name/value_element in collection
, que représentent name
et value_element
?
Dans une boucle for name/value_element in collection
, que représentent name
et value_element
?
Quel est le rôle du mot-clé continue
dans une boucle en Rust?
Quel est le rôle du mot-clé continue
dans une boucle en Rust?
Comment peut-on sortir prématurément d'une boucle en Rust?
Comment peut-on sortir prématurément d'une boucle en Rust?
Quel est le but des macros en Rust?
Quel est le but des macros en Rust?
Quelle est la différence entre une shared reference
et une exclusive reference
en Rust?
Quelle est la différence entre une shared reference
et une exclusive reference
en Rust?
Quel est l'équivalent d'un vecteur en Rust?
Quel est l'équivalent d'un vecteur en Rust?
Quelle est la fonction de Option
en Rust?
Quelle est la fonction de Option
en Rust?
Si une variable var2
de type Option
est égale à None
, que se passe-t-il lors de l'appel à var2.unwrap()
?
Si une variable var2
de type Option
est égale à None
, que se passe-t-il lors de l'appel à var2.unwrap()
?
Quel est le but du type Result
en Rust?
Quel est le but du type Result
en Rust?
Quel est l'impact de l'Ownership?
Quel est l'impact de l'Ownership?
Flashcards
Fonction main
Fonction main
Point de départ pour l'exécution du code Rust.
mut
mut
Mot-clé pour déclarer une variable modifiable.
const
const
Déclare une variable constante.
Opérateur logique If
Opérateur logique If
Signup and view all the flashcards
Match
Match
Signup and view all the flashcards
Boucle While
Boucle While
Signup and view all the flashcards
Boucle Loop
Boucle Loop
Signup and view all the flashcards
Break
Break
Signup and view all the flashcards
Continue
Continue
Signup and view all the flashcards
Macros
Macros
Signup and view all the flashcards
Box<T>
Box<T>
Signup and view all the flashcards
Inner doc comment
Inner doc comment
Signup and view all the flashcards
&dyn
&dyn
Signup and view all the flashcards
Option
Option
Signup and view all the flashcards
Result
Result
Signup and view all the flashcards
HashMap
HashMap
Signup and view all the flashcards
String
String
Signup and view all the flashcards
Lifetimes
Lifetimes
Signup and view all the flashcards
Enums
Enums
Signup and view all the flashcards
Traits
Traits
Signup and view all the flashcards
Study Notes
Fonction Principale
- La fonction principale est déclarée avec
fn main() {}
.
Variables
- Les variables sont déclarées avec
let mut nom_variable: type = valeur;
. - Le mot clé
mut
doit être présent si l'on souhaite modifier la variable. - Le type d'une variable peut être inféré.
let
peut être remplacé parconst
pour déclarer une constante.
Types de Données et Littéraux
- Entiers signés :
i8, i16, i32, i64, i128, isize
, Les littéraux exemple:-10, 0, 1_000, 123_i64
- Entiers non signés :
u8, u16, u32, u64, u128, usize
, Les littéraux exemple:0, 123, 10_u16
- Nombres à virgule flottante :
f32, f64
, Les littéraux exemple:3.14, -10.0e20, 2_f32
- Caractères Unicode :
char
, Les littéraux exemple:'a', 'α', '∞'
- Booléens :
bool
, Les littéraux exemple:true, false
Largeur des Types
- Les types
iN
,uN
, etfN
occupentN
bits en mémoire. isize
etusize
ont la taille d'un pointeur.char
occupe 32 bits.bool
occupe 8 bits.
Fonctions
- Les fonctions se définissent ainsi :
fn nom_fonction (parameter1 : type ,…, parameterN : type ) -> typeRetour { contenu }
- La valeur de retour d'une fonction est la dernière valeur utilisée dans le bloc, sans nécessité de
return
.
Blocs
- Les blocs sont définis par
{…}
. - La valeur d'un bloc est la dernière valeur ou variable à la fin du bloc.
- Si un bloc se termine par un
;
, sa valeur est()
. - Il est possible de déclarer une variable
static
pour qu'elle soit utilisable dans tous les blocs.
Opérateurs Logiques
if predicat { ... }
: Si la condition est vraie, faire.else if predicat { ... }
: Sinon si la condition est vraie, faire.else { ... }
: Sinon, faire.if let nomVar ...
: Teste si une variable suit un certain pattern.Match nom_variable {}
: opérateur conditionnel équivalent au switch.- Des opérateurs/conditions peuvent être ajoutés sur les valeurs dans le
match
.Value1 | value2 && value3 => block4
Value if predicate sur value => block5
Correspondance de motifs (structures, énumérations)
- Syntaxe générale:
Match nom_struct { typeStruct{attribute1 : value1, attribute2 : value2, … attributeN : valueN} => block1 }
- Teste si les attributs 1 à n de la struct ont les valeurs value1 à valueN.
typeStruct{attribute1 : nomVar} => block2
: Teste si l'attribut 1 existe et le stocke dans une nouvelle variable.typeStruct{attribute1,attribute2,.. } = > block3
: Teste si les attributs 1 et 2 existent, ignorant les autres.typeEnum::attribute( value ) => block
: Syntaxe pour les énumérations.
Boucles
while predicat { }
: Boucle tant que la condition est vraie.for name/value_element in collection { }
: Boucle pour chaque élément dans une collection.for name/value_element in collection { }
: Boucle pour chaque élément dans une collection.Loop { }
: Boucle infinie.Continue
: Permet de passer directement à l'itération suivante dans une boucle.Break
: Interrompt instantanément une boucle.
Contrôle de Boucle
- Il est possible de nommer une boucle pour l'interrompre ou continuer spécifiquement.
Fonctions Constantes
- Une fonction déclarée avec
const
ne peut utiliser ou renvoyer que des variables constantes, est inline, et son résultat est calculé à la compilation.
Macros
- Les macros sont des fonctions pouvant prendre un nombre indéfini de paramètres.
nomMacro !( param1,param2,…,paramN ) ;
: Syntaxe pour appeler une macro.
Collections
- Liste (Tableau)
- Syntaxe :
Let mut nomVar : [ type ; tailleListe ] = [ value1,… value_tailleListe ]
- Syntaxe alternative :
[ valueForNumber ; number ]
nomVar[ n ] = …
: Change la valeur à l'indexn
.- Il est possible d'itérer dans une liste avec
élément in nomListe
.
- Syntaxe :
Tuples
- Sintaxe :
Let nomTuple : ( typeValeur1 , …, typeValeurN ) = ( valeur1 ,…, valeur n )
- Il est possible d'associer des variables aux éléments d'un tuple avec
let (var1, …, varN) = tuple;
. - _ peut etre utilise pour ignorer une valeur dans un tuple.
- Exemple :
let (var1, _, var3, …, varN) = tuple;
.
- Exemple :
..
peut être utilisé pour ignorer les valeurs du début ou de fin.- Exemple :
let (.., varN-1,VarN) = tuple
- Exemple :
Références
- Référence partagée (lecture seule) :
let mut nomRef: &type_var_a_referer = &nomVariable ;
*nomRef
permet de récupérer la valeur de la variable stockée dans la référence.
- Référence exclusive :
let nomRef = &mut var
- Permet de modifier la valeur de la variable.
- Une seule référence exclusive par variable est autorisée.
- Une référence devient read-only si la variable est modifiée après sa déclaration.
- Une référence ne peut ni être nulle ni pointer vers une valeur hors du même bloc.
Slices
- Pointeur vers un ou plusieurs éléments d'une collection :
Let slide: &[type_collection] = &collection [i.. n];
- Ce code pointe vers les éléments de la collection d'indice k avec k appartenant à [i, n-1].
- Le type
&str
est un slice de bytes encodés en UTF-8 (&[u8]
). String
est similaire à unVec
avecT = u8
.
Structures
- Declaration :
struct Struct_name { attribute1 : type1 ; attribute2 : type2 ; };
- Récupérer un attribut :
Struct_Name.attribute
- Créer un objet d'une struct :
let mut var_name : struct_name{ attribute_1 : value, … , attribute_n : value }
Implémentation de Méthodes pour une Structure
- Syntaxe générale:
impl nomStruct { ... }
fn nomFunc(&self parameter1 : type ,…, parameterN : type ) ->typeRetour {}
&self
ne permet pas de modifier la struct (lecture seule partagée).&mut self
est utilisé pour modifier le contenu d'une struct (accès exclusif en écriture/lecture).- Accès aux attributs dans les méthodes:
self.attribute
- Equivalent d'un constructeur :
fn new ( parameter 1 : type1,… ) -> Self{ Self {attribute1 : value, …, attributeN : valueN }}
- Nécessite de donner une valeur à chaque attribut.
- La fonction doit se terminer par
Self{…}
pour retourner la structure.
TupleStruct
- Structure dont les noms des attributs ne sont pas importants:
struct struct_name (type1,…,typeN);
- Récupération d'un attribut:
struct_name.k
(k entre 0 et nombre d'attributs - 1) - Création d'un objet TupleStruct:
let var = struct_name(value1,…,value_N)
Traits
- Permettent d'ajouter des interfaces implémentables par des structures:
trait nomTrait { fn abstractFunc(&self,…) -> typeReturn; }
- La méthode de
nomTrait
doit être implémentée par une structure pour être utilisée:impl nomTrait for nomStruct{ fn abstractFunc(&self,…) -> typeReturn {…} }
- Héritage avec des traits:
trait nomTrait : superTrait {…}
- Association de types à un trait:
trait nomTrait { type typeReturn ; fn abstractFunc(&self,…) -> typeReturn; }
impl nomTrait for nomStruct{ type typeReturn = type ; fn abstractFunc(&self,…) -> typeReturn {…} }
- Dérivation automatique de traits suportés:
#[derive(trait1, …, traitN)] Struct nomStruct {}
Enums
- Type dont les valeurs possibles sont limitées et définies à la compilation:
enum name { value1, …, valueN, };
- Utilisation:
Enum_name ::value_k
(donne la valeur numéro k d'une énumération)
Aliases
- Déclaration d'un nouveau nom de type:
type name_type_1 = name_type_2
Generic Functions
- Implémentation de fonctions avec des types génériques (patrons):
fn nomfunc (param1 :type1 ,…, paramk : T,…, paramN : typeN) -> T {}
- Les éléments de type T peuvent être de n'importe quel type.
- On peut renvoyer un type défini.
- On identifie un type inconnu en le mettant entre
<>
après le nom de la fonction. - On peut vouloir qu'un type implémente un trait:
fn nomfunc (param1 :type1 ,…, paramk : T,…, paramN : typeN) -> T {}
- Les paramètres/Valeurs de retour de type T devront avoir un type implémentant T.
Generic Implementation
- Création de structures implémentant des types génériques:
struct Struct_name { attribute1 : T ;
Fonctions Génériques et Dynamiques
- Permettent d'utiliser les comportements (méthodes) des types/struct implémentant le type d'un paramètre en entrée : ainsi si B implémente A, et la fonction à pour entrée un paramètre de type A, alors si on passe à cette fonction une variable de type B, alors la fonction utilisera le comportement du type B.
fn generic (attribut1: &impl typeA)
&impl
: Rust créer une version de la fonction pour chaque type implémentanttypeA
.fn generic (attribut1: &dyn typeA)
&dyn
ne créer pas différentes versions de la méthode, mais recherche dynamiquement le bon type dans une vtable (virtual dynamic table) contenant l'ensemble des types implémentanttypeA
. La variable passée en paramètre doit être un pointeur.
Documentation et commentaires
- Annotations pour documenter le code:
/// commentaire
//! Inner doc comment
/*! Inner doc comment */
- Toute librairie publiée en Rust est documentée automatiquement sur docs.rs
Standard Library
- La librairie standard établit un ensemble de règles et de types.
Option
- Permet de stocker une valeur ou rien du tout (gestion de l'absence de valeur).
let mut var1: Option = var2;
- On peut utiliser Option pour tenter de récupérer la valeur d'une fonction pouvant ne rien renvoyer.
var2.unwrap()
: Récupère la valeur contenue dans l'option (panique siNone
).var2.expect(« message »)
: Récupère la valeur contenue (panique avec un message siNone
).
Result
- Permet de stocker le résultat d'une opération et d'indiquer si elle a réussi ou non :
Result = operation(…)
- Contient deux attributs :
Ok
etErr
. - Syntaxe avec
match
:match storedResult{ Ok(mut storedResult) => {…} Err(err) => {…} }
- err est le message d'erreur retourné si l'opération échoue.
String
- Liste de caractères encodés en UTF-8.
let mut var = String::new();
var.push_str(string)
: Ajoute un autre string à la fin.var.push(« c »)
: Ajoute un caractère.var.len
: Taille de la chaîne.var.count
: Nombre de caractères.var.capacity
: Nombre d'éléments max de la chaîne.
Vec
- Permet de faire un vecteur (tableau dynamique).
let mut v1 = Vec::new();
- Utilisable avec
push
,len
,capacity
. v1.retain( condition )
: Garde uniquement les éléments dev1
respectant la condition.v1.dedup()
: Supprime les éléments en doubles.
HashMap
let mut hmap = HashMap::new();
- Dictionnaire en Rust, associe une valeur à une clé :
hmap.insert( Stringkey , Intvalue );
- Insère une nouvelle donnée dans le dictionnaire.
hmap.containskey( key ) ;
: Renvoie vrai si hmap contient la cléhmap.len()
: Nombre de clés dans le dictionnairehmap.get( key )
: Récupère la valeur associée à la clé key
Comparaisons
- Il est possible de définir une relation
==
ou!=
pour des structures en implémentant le traitpartialeq
:impl PartialEq for typename{ fn eq(&self, other: &Self) -> bool { self.attribute == other.attribute } fn ne(&self, other: &Self) -> bool { self.attribute != other.attribute } }
- Il est aussi possible de définir des ordres
PartialOrd
.
Opérateurs
- On peut implémenter des opérateurs pour nos structs avec
std::ops::
:impl std::ops::Add for typename { type Output = Self; fn add(self, other: Self) -> Self { Self { attr1: self.attr1 + other. attr1, attr2: self. attr2 + other. attr2 } } }
From / Into / As
- from(): permet d'extraire une valeur d'un type vers unevaleur d'un autre type. Il faut que la valeur du type entre parenthèse implémente from pour ce type :
let one = i16::from(true);
- Into(): permet de caster lune valeur d'un type vers une valeur d'un autre type :
let one: i16 = true.into();
- As permet d'utiliser une variable comme une variable d'un autre type :
var as type
. - Utiliser
from
etinto
plutôt que cast.
Read et Write
- Permettent d'implémenter des fonctions permettant de lire des données sous format u8 (bytes) tel que des fichiers ou juste des chaînes de caractères.
Default
- Est un trait permettant d'implémenter une valeur par défaut à un type:
impl Default for type1 { fn default() -> type1{ valAttr1, valAttr2,… valAttrN } }
- Pour obtenir les valeurs par défaut d'un type on fait
nomType ::default()
Mémoire
- Deux types d'allocation mémoire en Rust : Stack(pile) et Heap (tas).
Stack(pile)
- Concerne les variables locales
- Tailles des valeurs fixes et connues à la compilation
- Très rapide, rust n’as qu’à déplacer un pointeur dans le stack
- Permet facilement un accès rapide à des zones mémoires souvent utilisés (cache mémoire) (memory locality)
Heap (tas)
- Stockage de valeurs en dehors des appels de fonctions
- Valeur de taille dynamique déterminée à l'exécution
- Plus lent que la pile
- Pas de garantie pour un accès rapide aux zones mémoires récurrentes (memory locality)
Ownership
- Chaque variable possède une valeur dont elle est propriétaire et un scope.
- Chaque valeur ne peut avoir qu'un seul propriétaire.
- Quand le scope arrive à sa fin (fin du block, fin de fonction), alors la variable est désallouée et sa valeur est supprimée de la mémoire.
- Lors d'un assignement par =, la variable initiale perd sa valeur et la nouvelle devient propriétaire.
- Toute tentative d'accès ou de modification de la variable initiale causera une erreur.
- Pour copier la valeur d'une variable sans perte de valeur, utiliser la fonction
clone()
. - Si un type implémente le trait
copy
, l'affectation d'une valeur par = devient une copie.- Ex : Deriver le trait de copy:
#[derive(Copy)] struct nomStruct {…}
- Ex : Deriver le trait de copy:
- Trait
Drop
: est appelé durant la désallocation (out of scope):impl Drop for nomStruct { fn drop(&mut self) { ... }}
Pointeurs
- Plusieurs types de pointeurs.
Box
- Pointeur vers une valeur du heap (valeurs stockées en dehors des appels de fonctions).
let var 1 = Box::new(value) ;
- Implémente le trait Deref.
Rc
- Reference counted shared pointer. Compteur du nombre de variables ayant accès au pointeur.
- La Valeur stockée dans le heap.
Borrowing
- Étant donné que l'affectation de la valeur d'une variable de à une autre supprime la valeur dans la variable initiale (principe d'ownership), on ne peut pas transmettre directement une variable comme paramètre de fonction. Cela se fait donc en transmettant une copie de la valeur à l'aide de la syntaxe suivante :
fn func(val1: &type1, val2: &type2) -> … { ... }
- Limitations de valeurs empruntées :
- On ne peut emprunter qu'une valeur qui appartient à la même portée (bloc) que la fonction.
- Règle d'aliasage : on ne peut avoir simultanément qu'une référence exclusive en écriture (mais autant de références partagées en lecture que l'on veut). Par exemple, si on déclare une référence exclusive sur une variable avant l'appel de la fonction, on ne peut pas utiliser la valeur de cette variable dans la fonction.
Cell/RefCell
Cell
: Permet de créer un pointeur avec un getter/setter sur la variable.let cell = Cell::new(value);
cell.set(value);
dbg!(cell.get());
- Ne peut pas être utilisé dans une variable déclarée comme « mutable ».
RefCell
: Marches similairement àCell
,borrow_mut()
est utilisé pour avoir une référence exclusive:let cell = RefCell::new(value);
let mut cell_ref = cell.borrow_mut();
*cell_ref = value
Lifetimes
- Chaque référence a une durée de vie plus courte que la durée de vie (portée) de la variable. La durée de vie par défaut est explicite (définie par le compilateur), mais elle peut être précisée par des annotations. Ceci est d'ailleurs obligatoire dans le cas d'une fonction si on veut retourner un pointeur.
- Syntaxe:
fn func &'a type1 -> &'a type1
Studying That Suits You
Use AI to generate personalized quizzes and flashcards to suit your learning preferences.