Rust est un langage comme un autre avec ses spécificités. Mais beaucoup s'en font tout un monde (une sorte d'élitisme inutile s'est installé autour de ce langage). J'espère que ce projet vous aidera à franchir le pas, mais n'oubliez pas de lire la documentation officielle (https://doc.rust-lang.org/book/), lire des livres, blog posts et demander aux copains, ...
Vous êtes dans un projet "Gitpodifié", donc vous n'avez rien à installer. Sinon, l'installation de Rust est plutôt triviale, je vous laisse en juger: https://doc.rust-lang.org/book/ch01-01-installation.html
Créez un nouveau projet Rust en utilisant Cargo (le gestionnaire de paquets et de projets de Rust). Dans votre terminal, exécutez :
cargo new 01-hello-world --name hello_world
cd 01-hello-worldOuvrez le fichier src/main.rs et remplacez le contenu par :
fn main() {
println!("👋 Hello, World 🌍!");
}Ensuite, exécutez votre programme avec la commande :
cargo runCréez un nouveau projet:
cargo new 02-variables --name variables
cd 02-variablesRust est un langage statiquement typé, donc vous devez déclarer le type de vos variables. Voici un exemple :
fn main() {
let x: i32 = 5;
let y: f64 = 3.14;
let is_rust_cool: bool = true;
println!("x = {}, y = {}, Rust is cool = {}", x, y, is_rust_cool);
}Ensuite, exécutez votre programme avec la commande :
cargo runCréez un nouveau projet:
cargo new 03-control-structure --name control_structure
cd 03-control-structureUtilisez if, else if, et else pour les conditions, et loop, while, ou for pour les boucles :
fn main() {
let number = 7;
if number % 2 == 0 {
println!("Even");
} else {
println!("Odd");
}
for i in 0..5 {
println!("Iteration: {}", i);
}
}Ensuite, exécutez votre programme avec la commande :
cargo runCréez un nouveau projet:
cargo new 04-functions --name functions
cd 04-functionsDéclarez des fonctions avec fn :
fn add(x: i32, y: i32) -> i32 {
x + y
}
fn main() {
let sum = add(3, 4);
println!("Sum: {}", sum);
}Ensuite, exécutez votre programme avec la commande :
cargo runCréez un nouveau projet:
cargo new 05-ownership-borrowing --name ownership_borrowing
cd 05-ownership-borrowing Rust utilise un système de possession unique pour gérer la gestion de la mémoire. Voici un exemple simple :
fn main() {
let s1 = String::from("Hello");
let s2 = s1; // ownership transférée à s2
// println!("{}", s1); // erreur car s1 ne possède plus la chaîne.
println!("{}", s2);
let s3 = String::from("Hello");
let s4 = &s3; // borrowing de l'ownership
println!("{}", s3); // Cela est autorisé grâce au borrowing.
println!("{}", s4);
}Ensuite, exécutez votre programme avec la commande :
cargo runet aussi un peu de programmation fonctionnelle
Créez un nouveau projet:
cargo new 06-structs-enums --name structs_enums
cd 06-structs-enums Définissez des structures de données avec struct et créez des énumérations avec enum :
struct Person {
name: String,
age: u32,
}
enum Status {
Success,
Failure(String),
}
fn main() {
let person = Person {
name: String::from("Alice"),
age: 30,
};
match person.age {
0..=17 => println!("Minor"),
18..=64 => println!("Adult"),
_ => println!("Senior"),
}
let result = Status::Success;
match result {
Status::Success => println!("Operation succeeded"),
Status::Failure(msg) => println!("Operation failed with message: {}", msg),
}
}Ensuite, exécutez votre programme avec la commande :
cargo run✋ Vous allez avoir quelques warnings, mais pas d'inquétude, ça va quand même s'exécuter:
Celui-ci, c'est parce que vous affectez une valeur Ă
name, mais vous ne la lisez pas
warning: field `name` is never read
--> src/main.rs:23:5
|
22 | struct Person {
| ------ field in this struct
23 | name: String,
| ^^^^
|
= note: `#[warn(dead_code)]` on by defaultLe compilateur estime que votre
enumn'est pas "reachable" par le reste du code. Si vous passez votreenumen publique (pub), le warning disparaîtra.
warning: variant `Failure` is never constructed
--> src/main.rs:29:5
|
27 | enum Status {
| ------ variant in this enum
28 | Success,
29 | Failure(String),
| ^^^^^^^Créez un nouveau projet:
cargo new 07-errors --name errors
cd 07-errors Utilisez Result pour gérer les erreurs :
fn divide(x: f64, y: f64) -> Result<f64, &'static str> {
if y == 0.0 {
Err("Cannot divide by zero")
} else {
Ok(x / y)
}
}
fn main() {
let result = divide(10.0, 2.0);
match result {
Ok(value) => println!("Result: {}", value),
Err(msg) => println!("Error: {}", msg),
}
}Ensuite, exécutez votre programme avec la commande :
cargo runâś‹ Alors, lorsque l'on vient du JavaScript comme moi, il y a un truc un peu "Ă©sotĂ©rique" dans la notation du type de retour de la fonction: Result<f64, &'static str> (et lĂ tu te dis que les gens qui font du Rust font ça pour pas que l'on fasse du Rust đź¤, je reconnais avoir eu la mĂŞme impression quand je me suis mis Ă Scala).
&'static str est une référence à une chaîne de caractères statique en cas d'erreur 🤔 ... 🤪
Allez, je re-essaie:
La notion de 'static en Rust se réfère à la durée de vie de la chaîne de caractères et à la manière dont cette chaîne est stockée en mémoire.
Une référence avec une durée de vie 'static signifie qu'elle pointe vers une région mémoire statique, dont la durée de vie est la totalité de l'exécution du programme. Concrètement, cela signifie que la chaîne de caractères à laquelle elle fait référence est stockée dans une région mémoire qui persiste pendant toute la durée de vie (d'exécution) du programme.
Créez un nouveau projet:
cargo new 08-strings-vectors --name strings_vectors
cd 08-strings-vectors Rust propose des types de données intégrés tels que String et Vec :
fn main() {
// String
let mut greeting = String::from("Hello, ");
greeting.push_str("world!");
println!("{}", greeting);
// Vec
let numbers = vec![1, 2, 3, 4, 5];
for num in &numbers {
println!("{}", num);
}
}Ensuite, exécutez votre programme avec la commande :
cargo runCréez un nouveau projet:
cargo new 09-threads --name threads
cd 09-threads Rust prend en charge le multithreading de manière plutôt simple et intuitive (mais attention, l'exemple est simple):
use std::thread;
use std::time::Duration;
fn main() {
// Créer un vecteur pour stocker les threads
let mut handles = vec![];
for i in 0..5 {
// Créer un nouveau thread pour chaque itération
let handle = thread::spawn(move || {
// Code exécuté dans chaque thread
for j in 0..3 {
println!("Thread {}: Iteration {}", i, j);
thread::sleep(Duration::from_millis(100)); // Simuler une tâche prenant du temps
}
});
// Ajouter le thread au vecteur
handles.push(handle);
}
// Attendre que tous les threads se terminent
for handle in handles {
handle.join().unwrap();
}
}Ensuite, exécutez votre programme avec la commande :
cargo runDans cet exemple, j'ai créé cinq threads, chacun exécutant une boucle. Les threads sont stockés dans un vecteur handles. La fonction thread::sleep simule une tâche qui prend du temps.
Ensuite, dans la deuxième boucle on attend que tous les threads se terminent à l'aide de la méthode join. Cela permet aux threads de s'exécuter de manière concurrente, affichant leurs sorties (println!("Thread {}: Iteration {}", i, j);) pendant que le programme principal attend qu'ils se terminent.
✋ vous avez du remarquer le mot clé mut au moment de la déclaration du vecteur handles. Le mot-clé mut est utilisé pour indiquer que la variable est mutable, c'est-à -dire qu'elle peut être modifiée après sa création. Cela s'applique principalement aux variables, mais peut également être utilisé pour rendre des références mutables, des champs de structures mutables, etc ...
Ceci était une introduction (très) rapide à Rust. Il vous reste encore du chemin, mais vous avez de quoi commencer sans stress.
Je vous recommande aussi ces guides d'introduction, complètement complémentaires au mien: