---
title: Cours de programmation séquentielle
subtitle: Types avancés
author: Orestis Malaspinas
<!-- date: 25 avril 2018 -->
sansfont: Sans Serif
---

# Vecteurs statiques

## `array`{.rust}

- Collection d'objet de **même** type dont le nombre est connu à la compilation.
- Ne peuvent pas changer de taille au cours de l'exécution (les éléments peuvent changer de valeur).
- Éléments alloués contigument dans la mémoire. <!-- Ajouter image -->
- Alloués sur la pile (en général).

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let entiers = [1, 2, 3, 4, 5];
    println!("Les 5 premiers entiers naturels: {:?}.", entiers); 

    let zeros: [i32; 10] = [0; 10]; // déclaration explicite du type
    println!("Dix zéros: {:?}.", zeros); 
}
</code></pre>

## Accès aux éléments

- On accède aux éléments à l'aide de l'opérateur `[index]`{.rust}, où `index`{.rust} est l'indice que nous voulons accéder.
- L'indice va de `0`{.rust} à `taille-1`{.rust}.

    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let jours = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi",
                   "Samedi", "Dimanche"];
    let premier = jours[0];
    let dernier = jours[6];

    println!("Le premier jour de la semaine est le {} et le dernier {}.", premier, dernier); 
}
    </code></pre>

- Il est **impossible** d'accéder un indice au delà de la taille du vecteur.

    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let jours = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi",
                   "Samedi", "Dimanche"];
    let _oups = jours[7];
}
    </code></pre>

## Modification des éléments

- Pour modifier les éléments utiliser `mut`.

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let mut entiers = [1, 2, 3, 4, 5];
    entiers[0] = -4;
    println!("Les 5 entiers : {:?}.", entiers); 
}
    </code></pre>

# $N$-uplets

## `Tuples` {.rust}

- Un $n-$tuplet est une *collection* ordonnée de $n$ objets.

    ```
    let tuple: (type1, type2, ...) = (val1, val2, ...); // le type peut être inféré
    ```
- Permet de regrouper plusieurs valeurs avec différents types dans un type composé.

    <pre><code data-trim="hljs rust" class="lang-rust">
    fn main() {
        let tuple: (f64, char, usize) = (1.0, 'c', 18usize); // type pas nécessaire

        println!("Un tuple {:?}", tuple); // affichage Debug

        let sans_type_tuple = (666, "abcdef"); // type inféré

        println!("Un autre tuple {:?}", sans_type_tuple); // affichage Debug
  }
    </code></pre>
- Pas forcément toujours pratique: on a pas d'identifiant pour les champs.

## Exemple

<pre><code data-trim="hljs rust" class="lang-rust">
fn area(w: usize, h: usize) -> usize {
    w * h
}

fn area_t(r: (usize, usize)) -> usize {
    r.0 * r.1
}

fn main() {
    let w = 10; 
    let h = 20;

    println!("Area = {}.", area(w,h));
    println!("Area with tuple = {}.", area_t((w,h)));
}
</code></pre>

## Destructuration

- Les $n$ objets d'un $n$-uple n'ont pas d'identifiant, juste un numéro.
- On peut destructurer un $n$-uplet avec la notation

  `let (a,b,c,...) = tuple;`{.rust}

- Les champs sont accessibles avec la notation 

  `
  let a = tuple.0;
  let b = tuple.1;
  `{.rust}

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let tuple = (1.0, 'c', 18usize);
    let (fl, ch, us) = tuple;
    println!("Le tuple destructuré: {}, {}, {}", fl, ch, us);

    let fl_ind = tuple.0;
    let ch_ind = tuple.1;
    let us_ind = tuple.2;
    println!("Le tuple re-destructuré: {}, {}, {}", fl_ind, ch_ind, us_ind); 
}
</code></pre>

# Structures

## `struct`{.rust} (1/3)

- Une structure est un type composé.
- Permet de regrouper des et de nommer des données.
- La syntaxe pour définir une structure est

    <pre><code data-trim="hljs rust">
struct Identifiant {
    id1: Type,
    id2: Type,
    ...
}
    </code></pre>

- Exemple: définition d'un étudiant (diant, diant)

    <pre><code data-trim="hljs rust">
struct EtudiantDiantDiant {
    nom: String,
    id: usize,
    actif: bool,
}
</code></pre>

## `struct`{.rust} (2/3)

- Pour utiliser une structure il faut en créer une **instance**.
- Pour ce faire il faut utiliser la syntaxe suivante

    <pre><code data-trim="hljs rust">
let etu = EtudiantDiantDiant {
    nom: String::from("Jean-Paul Dax"), 
    id: 0usize,
    actif: true,
};
</code></pre>

- Pour accéder aux champs d'une `struct`{.rust} il faut utiliser la syntaxe `instance.identifiant`{.rust}.
- Par défaut **tous les champs** d'une structure sont *immutables*.
- Pour les modifier il faut rendre **toute** la structure *mutable*.

<pre><code data-trim="hljs rust">
let mut etu = EtudiantDiantDiant {
    nom: String::from("Jean-Paul Dax"), 
    id: 0usize,
    actif: true,
};

etu.actif = false;
</code></pre>

## `struct`{.rust} (3/3)

- En ne donnant pas d'identifiant aux champs d'un `struct`{.rust}, on crée un `tuple struct`{.rust}.
- On accède aux champs comme avec un tuple normal `.0`{.rust}, `.1`{.rust}, ...
- Pour ce faire il faut utiliser la syntaxe suivante

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
  struct Point2d(i32, i32);

  let origine = Point2d(0,0);
  println!("L'origine est le point ({}, {}).", origine.0, origine.1);
}
</code></pre>

# Types énumérés

## `Enum`{.rust} (1/2)

- Permet de définir un type en *énumérant* toutes ses valeurs possibles.

    <pre><code data-trim="hljs rust">
enum TypeEnum {
    id1,
    id2,
    ...
}
    </code></pre>

- On peut créer une instance de chacune des variantes du type énuméré

    <pre><code data-trim="hljs rust">
let ins1 = TypeEnum::id1;
let ins2 = TypeEnum::id2;
...
    </code></pre>

- **Important**: `TypeEnum::id1`{.rust} et `TypeEnum::id2`{.rust} sont tous les deux de type `TypeEnum`{.rust}.

    <pre><code data-trim="hljs rust" class="lang-rust">
    enum TypeEnum {
        id1,
        id2,
    }

    fn foo(enum_type: TypeEnum) { }

    fn main() {
        foo(TypeEnum::id1); // appel valide
        foo(TypeEnum::id2); // appel également valide
    }
    </code></pre>

## `Enum`{.rust} (2/2)

- On peut également associer des valeurs avec n'importe quel variante de l'enum.

<pre><code data-trim="hljs rust">
struct TypeStruct {
    // détails pas importants
};

enum TypeEnum {
    id1(char, char), // deux char
    id2{x: usize},   // struct anonyme 
    id3(TypeStruct), // struct
}

let ins1 = TypeEnum::id1('a','b');
let ins2 = TypeEnum::id2({x: 12usize});
let ins2 = TypeEnum::id3(TypeStruct::new());
</code></pre>

# Pattern matching

## `match`{.rust} (1/3) 

- Structure de contrôle extrêmement puissante.
- Comparaison entre une valeurs et une série de *patterns* afin de décider d'une action à effectuer.
- Toutes les possibilités sont obligatoirement traitées.

<pre><code data-trim="hljs rust" class="lang-rust">
enum TypeEnum {
    id1,
    id2,
    id3,
}

fn main() {
    let data = TypeEnum::id1;
    let num = 
        match data {
            TypeEnum::id1 => 1,
            TypeEnum::id2 => 2,
            TypeEnum::id3 => 3,
        };
    println!("num = {}", num);
}
</code></pre>

## `match`{.rust} (2/3)

- Dans certains cas, on veut le même comportement pour plusieurs `patterns`.

<pre><code data-trim="hljs rust" class="lang-rust">
enum TypeEnum {
    id1,
    id2,
    id3,
}

fn main() {
    let data = TypeEnum::id3;
    let num = 
        match data {
            TypeEnum::id1 => 1,
            _ => 2,
        };
    println!("num = {}", num);
}
</code></pre>

## `match`{.rust} (3/3)

- Pour lier une valeur stockée dans un `Enum`{.rust}

<pre><code data-trim="hljs rust">
enum AnimalMythique {
    Chupacabra,
    Dahu,
    ChevalAile(Pays), // Le type Pays est défini avant
}

fn pays_dorigine(animal: AnimalMythique) {
    match animal {
        AnimalMythique::Chpacabra => println!("Mexique"),
        AnimalMythique::Dahu => println!("Suisse"), // Oui il Suisse.
        AnimalMythique::ChevalAile(pays) => println!("{}", pays);
    },
}
</code></pre>

<!-- # Options

- Un type énuméré particulièrement utile est le type `Option`{.rust}
```{.lang-rust}
enum Option<T> { // <T> est une notation pour un type générique
    Some(T),
    None,
}
```
- Type utilisé lorsque une valeur peut être "quelque chose" ou "rien".
- Exmple: la division

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let num = 1;
    let denum = 4;

    let div = 
        if denum == 0 {
            None
        } else {
            Some(num / denum)
        };

    match div {
        Some(d) => println!("{} divisé par {} donne {}", num, denum, d),
        None => println!("Cette division n'existe pas."),
    }
}
</code></pre> -->
