Rust

Rust est un langage bas-niveau comme C, mais plus sûr et qui permet la programmation générique.

Immutabilité par défaut

#![allow(unused)]
fn main() {
    let x = 1;
    x = 2; // erreur
}
#![allow(unused)]
fn main() {
    let mut x = 1;
    x = 2; //ok
}

Types

Les types sont inférés. Pas obligé de tout dire.

#![allow(unused)]
fn main() {
    let x = 1;
}

Mais on peut aussi dire :

#![allow(unused)]
fn main() {
    let x: i32 = 1;
}

Contrairement au C, les noms des types sont clairs.

  • Qu'est ce que i8 ? Un entier sur 8 bits. Un char en C.

  • Qu'est ce que u8 ? Un entier non signé sur 8 bits. Un unsigned char en C.

  • Qu'est ce que f64 ? Un flottant sur 64 bits. Un double en C.

Fonctions

#![allow(unused)]
fn main() {
fn addition(a: i32, b: i32) -> i32 {
    return a + b;
}

println!("{:?}", addition(1, 2));
}

Slices

Un slice un morceau de la mémoire. En gros, c'est un pointeur sur une zone mémoire et une taille.

#![allow(unused)]
fn main() {
let A = [0, 1, 2];
println!("{:?}", A);
let slice = &A[1..];
println!("{:?}", slice);
}

Le & veut dire qu'on met l'adresse mémoire (et la taille) dans slice.

TODO: pourquoi on a pas besoin de déréfencer à la ligne 4 ?

Les conditionnelles sont des expressions

#![allow(unused)]
fn main() {
    println!("{:?}", if 1 < 2 {3} else {4});
}

Pattern-matching

Le pattern maching ou filtrage par motif permet de faire une conditionnelle sur expression.

Mais attention ce code ne marche pas :

#![allow(unused)]
fn main() {
let s = "hello";

match s {
    "bonjour" => {println!("tu parles français")}
    "hello" => {println!("tu parles anglais")}
    "guten tag" => {println!("tu parles allemand")}
}
}

Pourquoi ne fonctionne-t-il pas d'après vous ? Car Rust est "sûr". Il veut être que vous traitiez tous les cas.

On peut écrire :

#![allow(unused)]
fn main() {
let s = "hello";

match s {
    "bonjour" => {println!("tu parles français")}
    "hello" => {println!("tu parles anglais")}
    "guten tag" => {println!("tu parles allemand")}
    _ => {println!("tu dis n'importe quoi")}
}
}
#![allow(unused)]
fn main() {
let age: u8 = 25;

match age {
    0..=3 => println!("bébé"),
    4..=18 => println!("mineur"),
    19.. => println!("grande personne de {:?} ans", age)
}
}

Boucles

#![allow(unused)]
fn main() {
let mut i: i32 = 0;
while i < 10 {
    println!("coucou !");
    i += 1;
}
}

Les boucles for s'appuie sur des objets (comme 0..4) qui peuvent être converti en itérateur :

#![allow(unused)]
fn main() {
for i in 0..4 {
    println!("{}", i);
}
}

Enum

enum Item {
    Book(f64, String, i64),
    Mug(f64, String),
    Shirt(f64, String, i32, i32)
}

fn main() {
    let item = Item::Shirt(10.0, "miaou".to_string(), 0, 2);

    match item {
        Item::Book(price, title, nb_pages) => &println!("The book {} is available!", title),
        Item::Mug(price, design) => &println!("Mug with {} available!", design),
        Item::Shirt(price, design, color, size) => &println!("Shirt with {} of size {} available!", design, size),
    };
}

Dans un jeu vidéo au tour par tour, on peut représenter une action avec un enum :

#![allow(unused)]
fn main() {
enum Action {
    Bouger(piece: Piece, nouvelle_position: Position),
    Passer
}
}