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

# Les types

## Qu'est-ce qu'un type

- *Un système décrivant ce qui peut être contruit dans un programme.*
- Permet au compilateur **ET** au programmeur de raisonner sur un programme.
<pre><code data-trim="hljs rust">
    4 + 12; //  = 16 (entier)
1 + "a"; // aucun sens erreur de compilation (ou pas)
</code></pre>
- Deux sous-catégories de systèmes de type:
    * Statiquement ou dynamiquement typé (types connus à la compilation ou pas).
    * Faiblement ou fortement typé (les types peuvent pas être convertis implicitement ou pas).

## Les types en rust

- Langage **statiquement et fortement typé**: tous les types sont connus **à la compilation** et la conversion entre les types doit être **explicite**.
- Les types sont **inférés** quand cela est possible.
- Il est parfois nécessaire d'annoter le type explicitement.

    <pre><code data-trim="hljs rust" class="lang-rust">
    fn main() {
        let x:i32 = 5; // entier 32 bits dont le type est annoté

        let y = 5; // entier 32 bits dont le type est inféré

        println!("Ces deux lignes sont équivalentes x={} et y={}", x, y); // affichage
    }
    </code></pre>

- Il exits plusieurs types de base:
    - Les entiers.
    - Les nombres à virgule flottante.
    - Les booléens.
    - Les charactères.

# Les types numériques

## Les entiers (1/3)

- Il existe 5 tailles d'entiers (8, 16, 32, 64, et 128 bits) qui viennent en *signé* ou *non-signé*.
- Également en taille dépendant de l'architecture
    - `isize`{.rust} entier signé 32 ou 64 bits.
    - `usize`{.rust} entier non-signé 32 ou 64 bits.

+---------------+---------------+--------------------+
|Longueur       | Signé         | Non-signé          |
+===============+===============+====================+
| 8 bits        | `i8`{.rust}   | `u8`{.rust}        |
+---------------+---------------+--------------------+
| 16 bits       | `i16`{.rust}  | `u16`{.rust}       |
+---------------+---------------+--------------------+
| 32 bits       | `i32`{.rust}  | `u32`{.rust}       |
+---------------+---------------+--------------------+
| 64 bits       | `i64`{.rust}  | `u64`{.rust}       |
+---------------+---------------+--------------------+
| 128 bit       | `i128`{.rust} | `u128`{.rust}      |
+---------------+---------------+--------------------+
| 32 ou 64 bits | `isize`{.rust}| `usize`{.rust}     |
+---------------+---------------+--------------------+

## Les entiers (2/3)

- Par défaut un entier est de type `i32`{.rust}.
- Les types `isize`{.rust} et `usize`{.rust} sont typiquement pour indéxer des collections.
- On peut spécifier le type d'un entier:
	- `42u8`{.rust} est un entier 8 bits non signé.
	- `42isize`{.rust} est un entier de 32 ou 64 bits signé.
- Pour améliorer la lisibilité on peut également ajout des "_":
	- On peut écrire `1000000`{.rust} comme `1_000_000`{.rust}
- On ne peut **pas** convertir implicitement d'un type à un autre.

    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x:i64 = 5i32; // entier 32 bits dans une variable 64 bits
}
    </code></pre>

- On peut convertir entre les entiers à l'aide de `as`{.rust}.

    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x:i64 = 5i32 as i64; // entier 32 bits dans une variable 64 bits

    println!("Conversion de 32 en 64 bits pour x={}.", x); // affichage
}
    </code></pre>

## Les entiers (3/3)

- En mode *debug*, un dépassement d'entier produira une erreur à l'exécution.
    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
	let x = 12341324;
	let y = 12341234;

	println!("L'entier x vaut {}.", (x*y) as i32); // affichage   
}
    </code></pre>
- **Attention**: En mode *release*, cela ne sera pas le cas.
    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x:i32 = 12345678; 
    let y:i32 = 12345678; 

    println!("L'entier x vaut {}.", x*y); // affichage   
}
    </code></pre>


## Les nombres à virgule flottante

- Il existe deux tailles de nombres à virgule flottante (32 et 64 bits):
	- `f32`{.rust},
	- `f64`{.rust}.
- Par défaut un nombre à virgule flottante est un `f64`{.rust}
- On ne peut **pas** convertir implicitement d'un type à un autre.

    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x:f64 = 3.14159265359f32; // flottant 32 bits en flottant 64 bits
}
    </code></pre>

- On peut convertir entre les types de base avec `as`{.rust}.

    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x = 3.14159265359f64 as f32; // flottant 64 bits en flottant 32 bits

    println!("Conversion de pi en 32 bits, x = {}.", x); // affichage

    let y = 3.14159265359f64 as isize; // flottant 64 bits en entier 

    println!("Conversion de pi en entier 64 bits, y = {}.", y); // affichage
}
    </code></pre>

## Les opérations arithmétiques

- Toutes les opérations arithmétiques standard: `+, -, *, /, %`{.rust}

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let addition = 3 + 8;
    println!("La valeur de l'addition est: {}", addition);

    let soustraction = 3.5 - 8.1;
    println!("La valeur de la soustraction est: {}", soustraction);

    let multiplication = -3.33 * 3.33;
    println!("La valeur de la multiplication est: {}", multiplication);

    let division = 7 / 2; // division entière
    println!("La valeur de la division est: {}", division);
}
</code></pre>

## Assignations

- Opérations arithmétiques et assignations: `+=, -=, *=, /=, %=`{.rust}.

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let mut addition = 3;
    addition += 5;
    println!("La valeur de l'addition est: {}", addition);

    let mut multiplication = 3.5;
    multiplication *= - 8.1;
    println!("La valeur de la multiplication est: {}", multiplication);
}
</code></pre>

# Les types booléens

## Les booléens

- Une variable booléenne est de type `bool`{.rust}.
- Elle peut prendre deux valeurs:
    - `true`{.rust}
    - `false`{.rust}
- La façon typique d'utiliser les booléens sont les structures de contrôle: `if`{.rust}, `while`{.rust}, ...
- Peut se convertir en entier (l'inverse est faux).

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x = true; // Booléen inféré vrai
    println!("La variable x est {}.", x); // affichage

    let x: bool = false; // Booléen faux
    println!("La variable x est {}.", x); // affichage

    let x = false as i32; // Booléen faux
    let y = true as i32; // Booléen faux
    println!("False est {}, et True est {}.", x, y); // affichage
}
</code></pre>

## Les opérations booléennes

- Comparaisons logiques `==, !=, &&, ||, <, >, <=, >=`{.rust}

    <pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x = 3;
    let y = 8;
    println!("{} est-il égal à {}? {}", x, y, x == 8);
    println!("{} est-il différent de {}? {}", x, y, x != 8);
}
    </code></pre>

- Comparaisons bit à bit:
    - Et: `&`{.rust}
    - Ou: `^`{.rust}

- Comparaisons bit à bit et assignations: `&=, ^=`{.rust}.

# Le type charactère

## Les charactères

- Une variable de type **charactère** est notée `char`{.rust}.
- Elle contient toute valeur **unicode scalaire**, soit environ 137000 charactères (pas seulement du ASCII!).
- Un charactère est toujours mis entre ' '.
- Composants du type `String`{.rust}.

<pre><code data-trim="hljs rust" class="lang-rust">
fn main() {
    let x = 'a'; // Le charactère a

    println!("La variable x est {}.", x); // affichage

    let chat = '😻';

    println!("La variable chat est {}.", chat); // affichage
}
</code></pre>

# Les types composés

- On peut contruire des types plus complexes (composés) à partir de types de base que nous venons de voir:
    - La type `Struct`{.rust}
    - Le type `Tuple`{.rust}
    - Le type `Enum`{.rust}
    - Le type `Array`{.rust}
    - Le type `Vec`{.rust}
    - Le type `String`{.rust}
    - ... 
    
