Bases du langage Rust

Choose a study mode

Play Quiz
Study Flashcards
Spaced Repetition
Chat to Lesson

Podcast

Play an AI-generated podcast conversation about this lesson
Download our mobile app to listen on the go
Get App

Questions and Answers

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?

  • `i64`
  • `i128`
  • `u64` (correct)
  • `isize`

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?

<p>Il attribue le type en fonction de la première utilisation de la variable, comme une opération ou un passage en paramètre. (D)</p> Signup and view all the answers

Qu'est-ce qu'un bloc en Rust?

<p>Une section de code délimitée par des accolades <code>{}</code>. (A)</p> Signup and view all the answers

Quelle est la valeur d'un bloc en Rust s'il se termine par un point-virgule (;)?

<p>La valeur est <code>()</code> (unité). (C)</p> Signup and view all the answers

Quelle est la principale différence entre let et const lors de la déclaration de variables en Rust?

<p><code>let</code> crée une variable immutable au moment de la compilation; <code>const</code> crée une constante dont la valeur doit être connue au moment de la compilation. (C)</p> Signup and view all the answers

Dans quel but peut-on déclarer une variable static dans Rust?

<p>Pour créer une variable qui est utilisable dans tous les blocs de code. (A)</p> Signup and view all the answers

Quelle est la fonctionnalité de l'opérateur if let en Rust?

<p>Il teste si une variable correspond à un certain pattern et exécute un bloc de code en conséquence. (C)</p> Signup and view all the answers

Comment fonctionne l'instruction match en Rust par rapport à un switch dans d'autres langages de programmation?

<p><code>match</code> est plus expressif et permet de faire du pattern matching sur des valeurs, offrant plus de flexibilité. (C)</p> Signup and view all the answers

Dans une boucle for name/value_element in collection, que représentent name et value_element?

<p><code>name</code> est l'index de l'élément et <code>value_element</code> est la valeur de l'élément. (C)</p> Signup and view all the answers

Quel est le rôle du mot-clé continue dans une boucle en Rust?

<p>Il passe directement à l'itération suivante de la boucle. (D)</p> Signup and view all the answers

Comment peut-on sortir prématurément d'une boucle en Rust?

<p>En utilisant le mot-clé <code>break</code>. (C)</p> Signup and view all the answers

Quel est le but des macros en Rust?

<p>Définir des fonctions pouvant prendre un nombre indéfini de paramètres. (C)</p> Signup and view all the answers

Quelle est la différence entre une shared reference et une exclusive reference en Rust?

<p>Une <code>shared reference</code> est immutable, tandis qu'une <code>exclusive reference</code> est mutable. (B)</p> Signup and view all the answers

Quel est l'équivalent d'un vecteur en Rust?

<p><code>Vec</code> (D)</p> Signup and view all the answers

Quelle est la fonction de Option en Rust?

<p>Stocker une valeur ou rien du tout. (A)</p> Signup and view all the answers

Si une variable var2 de type Option est égale à None, que se passe-t-il lors de l'appel à var2.unwrap()?

<p>Le programme panique et s'arrête. (B)</p> Signup and view all the answers

Quel est le but du type Result en Rust?

<p>Stocker le résultat d'une opération et indiquer si elle a réussi ou échoué. (D)</p> Signup and view all the answers

Quel est l'impact de l'Ownership?

<p>Chaque valeur a un seul propriétaire et un scope clair, évitant les dangling pointers et les fuites de mémoire. (B)</p> Signup and view all the answers

Flashcards

Fonction main

Point de départ pour l'exécution du code Rust.

mut

Mot-clé pour déclarer une variable modifiable.

const

Déclare une variable constante.

Opérateur logique If

Exécute un bloc de code si une condition est vraie.

Signup and view all the flashcards

Match

Structure de contrôle de flux équivalente à switch.

Signup and view all the flashcards

Boucle While

Répète un bloc de code tant qu'une condition est vraie.

Signup and view all the flashcards

Boucle Loop

Répète un bloc de code indéfiniment.

Signup and view all the flashcards

Break

Quitte instantanément une boucle.

Signup and view all the flashcards

Continue

Passe directement à l'itération suivante d'une boucle.

Signup and view all the flashcards

Macros

Fonction pouvant prendre un nombre indéfini de paramètres.

Signup and view all the flashcards

Box<T>

Pointeur vers une valeur stockée dans le heap.

Signup and view all the flashcards

Inner doc comment

Nom donné aux commentaires documentant un élément à l'intérieur d'un block, struct, ou une fonction.

Signup and view all the flashcards

&dyn

Table dynamique virtuelle contenant tous les types implémentant typeA.

Signup and view all the flashcards

Option

Permet de stocker une valeur ou rien.

Signup and view all the flashcards

Result

Stocke le résultat d'une opération.

Signup and view all the flashcards

HashMap

Dictionnaire associant une valeur à une clé.

Signup and view all the flashcards

String

Bibliothèque de caractères encodés en UTF-8.

Signup and view all the flashcards

Lifetimes

Pointeur dont la durée de vie doit être inférieure à la durée de vie (scope) de la variable.

Signup and view all the flashcards

Enums

Type dont les valeurs possibles sont limitées et définies au moment de la création de l'énum.

Signup and view all the flashcards

Traits

Permet d'ajouter des interfaces implémentables par des structs.

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é par const 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, et fN occupent N bits en mémoire.
  • isize et usize 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'index n.
    • Il est possible d'itérer dans une liste avec élément in nomListe.

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;.
  • .. peut être utilisé pour ignorer les valeurs du début ou de fin.
    • Exemple : let (.., varN-1,VarN) = tuple

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 à un Vec avec T = 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émentant typeA.
    • 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émentant typeA. 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 si None).
  • var2.expect(« message »): Récupère la valeur contenue (panique avec un message si None).

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 et Err.
  • 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 de v1 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 dictionnaire
  • hmap.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 trait partialeq:
    • 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 et into 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 {…}
  • 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.

Quiz Team

Related Documents

More Like This

Concepts de base de Rust
38 questions

Concepts de base de Rust

ImportantJasper9535 avatar
ImportantJasper9535
Introduction à Rust
20 questions

Introduction à Rust

AdventuresomeDravite avatar
AdventuresomeDravite
Introduction à Rust: variables et types
20 questions
Use Quizgecko on...
Browser
Browser