diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 17b6abb350430e8ffb0986b5faf19cb6a93ca26e..e3ee109776442d822fe11371f8181ec9f7d553e0 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -6,5 +6,4 @@
 - [Part 01](./part01.md)
 - [Part 02](./part02.md)
 - [Part 03](./part03.md)
-
-
+- [Part 04](./part04.md)
diff --git a/book/src/part04.md b/book/src/part04.md
new file mode 100644
index 0000000000000000000000000000000000000000..e9184b7641a624e8a5809be5be6a9858dc061c1b
--- /dev/null
+++ b/book/src/part04.md
@@ -0,0 +1,190 @@
+# Discussion du code `part04`
+
+Dans cette partie nous discutons de [ce code](#le-code).
+
+## Concepts
+
+Les concepts abordés dans cet exemple sont:
+
+1. [Bind et move.](#bind-et-move)
+2. [Ownership et borrowing.](#ownership-et-borrowing)
+
+## Discussion
+
+### Bind et move
+
+On l'a déjà brièvement mentionné dans la [partie 2](part02.md) l'instruction 
+
+```rust,no_run
+let a = 2;
+```
+
+fait plusieurs choses:
+
+1. Elle alloue l'espace pour un entier 32 bits.
+2. Initialise la mémoire avec la valeur `2`.
+3. Lie (bind en anglais) la variable (l'identifiant) `a` avec cet espace mémoire.
+
+Quand on sort de la portée (scope en anglais) la variable est plus accessible et la mémoire est automatiquement libérée (l'espace mémoire
+où est contenue la valeur `2` est libéré automatiquement). Cela se passe aussi en C, sauf quand on a fait un `malloc()` explicite.
+
+Si on écrit le code un peu plus compliqué
+```rust,compile_fail
+{{#include ../../codes/rust_lang/part04/src/main.rs:something_or_nothing}}
+fn main() {
+    let a = SomethingOrNothing::new(1);
+    let _b = a;
+    let _c = a;
+}
+```
+Ici ce code ne compile pas, car nous ne pouvons lier une valeur qu'à **une seule variable** par défaut.
+On dit que les données ne peuvent avoir qu'un seul propriétaire (owner en anglais).
+Ainsi, quand on fait 
+```rust,ignore
+let a = SomethingOrNothing::new(1);
+let _b = a;
+```
+on donne la propriété de la valeur `SomethingOrNothing::new(1)` à la variable `a`. Puis, quand transfère la propriété de la valeur
+`SomethingOrNothing::new(1)` à la variable `_b`. Ainsi, `a` n'est plus lié à `SomethingOrNothing::new(1)` et ne peut plus rien transférer
+comme données. Donc quand on fait 
+
+```rust,ignore
+let _c = a;
+```
+
+le compilateur refuse de nous laisser faire, car les données liées à `a` ont déjà été déplacées (moved en anglais) dans `_b`.
+
+Pour certains types, comme les `i32` (ou tous les types qui implémentent le trait `Copy`)
+une copie implicite est faite, et on ne déplace ainsi pas la propriété de la valeur mais on en crée
+une nouvelle qui est liée aux variables.
+
+Cette règle est **très importante** et a des implications très fortes en Rust (c'est aussi le cas dans tous les langages
+mais ça passe un peu plus inaperçu, car le compilateur ne se plaint pas). On dit que Rust empêche l'*aliasing*.
+On retrouve cette difficulté quand on passe un argument à une fonction. Si le type de la variable passé en argument
+n'est pas copiable, la propriété de la valeur est passée à l'argument de la fonction.
+Ainsi au moment de quitter la fonction la valeur est détruite et la mémoire liée à la valeur libérée
+comme dans le code suivant
+```rust,compile_fail
+{{#include ../../codes/rust_lang/part04/src/main.rs:something_or_nothing}}
+fn print<T: std::fmt::Display>(val: SomethingOrNothing<T>) {
+    match val {
+        SomethingOrNothing::Nothing => println!("Nothing."),
+        SomethingOrNothing::Something(val) => println!("Something is: {}", val),
+    }
+}
+fn main() {
+    let a = SomethingOrNothing::new(1);
+    print(a);
+    print(a);
+}
+```
+Ici lors du premier appel à `print(a)` la propriété de la valeur `SomethingOrNothing::new(1)` est transférée à l'argument `val` de la fonction
+`print(val)`. Lorsqu'on sort de la portée de la fonction la variable `val` est détruite et toutes les données qui vont avec.
+Comme la variable `a` n'est plus propriétaire d'aucune donnée, le second appel à `print(a)` échoue à la compilation.
+
+Une solution est d'implémenter le trait `Copy` pour `SomethingOrNothing<T>`, mais bien que cela puisse être acceptable
+pour un petit type comme celui-ci, en général le coût de performance serait énorme on devait répéter des copies
+qui prennent beaucoup de place en mémoire.
+
+Mais alors comment faire pour afficher un `SomethingOrNothing<T>` sans implémenter le trait `Copy`?
+
+### Ownership et borrowing
+
+Le Rust nous offre un moyen d'*emprunter* (borrow) les variables pour éviter d'avoir à faire des copies dans tous les sens
+ou de devoir toujours retourner les variables passées en argument.
+
+```rust
+{{#include ../../codes/rust_lang/part04/src/main.rs:something_or_nothing}}
+{{#include ../../codes/rust_lang/part04/src/main.rs:print}}
+fn main() {
+    let a = SomethingOrNothing::new(1);
+    print(&a);
+    print(&a);
+}
+```
+
+Dans ce code on voit que la fonction `print` a la signature suivante
+```rust,ignore
+fn print<T: std::fmt::Display>(val: &SomethingOrNothing<T>)
+```
+et le type de `val` est une **référence** vers un `SomethingOrNothing<T>` (il faut noter le `&` avant le type). La référence en Rust est un moyen d'emprunter
+la propriété d'une valeur. Ainsi quand on va sortir de la portée de la fonction, la variable `val`, qui est une référence
+va être détruite, mais les données qui sont liées à cette référence ne le seront pas. C'est pour cela que contrairement à
+ce qui se passe dans la section [Bind et move](#bind-et-move) on peut appeler deux fois la fonction `print(&val)`.
+Il faut bien noter que la *référence* a la syntaxe `&<variable>` comme en C.
+
+#### Exercice
+
+Corrigez ce code pour qu'il compile (sans enlever de lignes évidemment)
+
+```rust,editable,compile_fail
+{{#include ../../codes/rust_lang/part04/src/main.rs:something_or_nothing}}
+fn main() {
+    let a = SomethingOrNothing::new(1);
+    {
+        let b = a;
+        // imagine that some thing may happen here with b
+    }
+    let c = a;
+}
+```
+
+On constate dans notre code qu'il y a assez peu de modifications pour éviter les copies
+implicites et passer par des emprunts. Pour résumer, on a changé la signature de trois fonctions:
+`print()`, `print_tab()`, et `find_min()`.
+
+La fonction `print()` a déjà été discutée plus haut, et nécessite simplement
+l'ajout d'une référence vers un `SomethingOrNothing<T>` pour que la valeur soit
+prêtée à `val` dans la fonction
+```rust,ignore
+{{#include ../../codes/rust_lang/part04/src/main.rs:print}}
+```
+Ainsi, les valeurs de `SomethingOrNothing<T>` ne sont pas détruites à l'appel de `print()`.
+
+La fonction `print_tab()`, de façon similaire, nécessite le passage de la référence
+vers le tableau statique `&[T; SIZE]`
+
+```rust,ignore
+{{#include ../../codes/rust_lang/part04/src/main.rs:print_tab}}
+```
+
+La boucle for nécessite une discussion plus approfondie. En effet,
+dans cette fonction `tab` est une référence vers un tableau. Ainsi,
+on ne peut pas itérer sur ses éléments de façon standard. En effet,
+cela nécessiterait de "move" ou transférer la propriété de la valeur
+sur laquelle on itère.
+
+Le compilateur de Rust ne l'autoriserait jamais. Le langage nous facilite donc la vie en itérant sur
+les références des valeurs contenues dans le tableau (dont le type est générique, rappelons le).
+Donc si on annotait explicitement le type de `t` dans la boucle `for` on aurait:
+```rust,ignore
+for t: &T in tab
+```
+On constate aussi que le langage devine qu'on ne veut pas afficher la valeur de la référence (son adresse mémoire)
+mais affiche directement la valeur elle même quand on appelle la macro `print!()`
+```rust,ignore
+print!("{} ", t);
+```
+
+Finalement, nous avons également modifié la fonction `find_min()`. 
+```rust,ignore
+{{#include ../../codes/rust_lang/part04/src/main.rs:find_min}}
+```
+Outre l'argument qui est une référence à un tableau statique comme dans les deux autres fonctions
+discutées précédemment, on a une nouvelle syntaxe dans la boucle `for`
+```rust,ignore
+for t in tab {
+    current_minimum = current_minimum.min(SomethingOrNothing::new(*t));
+}
+```
+On constante qu'on doit déréférencer `t` (appeler `*t`), car `t` est une référence vers `T` (il est de type `&T`), car la fonction `new()` s'attend à un `T` et non à un `&T`. 
+L'opérateur `*<variable>` est l'opérateur de déréférencement et cette syntaxe est la même que celle du C.
+Si par malheur on oubliait le `*t` on aurait une erreur de compilation, car 
+le vérificateur de type du Rust ne laisse pas passer ce genre de choses.
+
+## Le code
+
+```rust
+{{#rustdoc_include ../../codes/rust_lang/part04/src/main.rs:main}}
+```
+
diff --git a/codes/rust_lang/part04/src/main.rs b/codes/rust_lang/part04/src/main.rs
index 08d81e3bd4c5714ca811ecdaf24cff439bea1bc0..551847bdd0f249696f219da2dc3c298f1518caa1 100644
--- a/codes/rust_lang/part04/src/main.rs
+++ b/codes/rust_lang/part04/src/main.rs
@@ -1,34 +1,29 @@
+/* ANCHOR: all */
+
 /*!
 Part04 illustrates the concepts of **Ownership** and **Borrowing**. It also
 presents the manual implementation of [Clone] and [Copy].
 */
-
-// Rust basics:
-//     - Ownership
-//     - Borrowing
-//     - Clone
-//     - Copy
-
-// An generic enumerated type that has two variants.
-//
-// - Nothing
-// - Something
+// ANCHOR: something_or_nothing
 enum SomethingOrNothing<T> {
-    // A [SomethingOrNothing::Nothing]
     Nothing,
-    // A [SomethingOrNothing::Something] encapsulating a T
     Something(T),
 }
+impl<T> SomethingOrNothing<T> {
+    fn new(val: T) -> SomethingOrNothing<T> {
+        SomethingOrNothing::Something(val)
+    }
+}
+// ANCHOR_END: something_or_nothing
 
-impl<T: std::fmt::Display> SomethingOrNothing<T> {
-    // A static function that prints the content of a SomethingOrNothing.
-    fn print(&self) {
-        match self {
-            SomethingOrNothing::Nothing => println!("Nothing."),
-            SomethingOrNothing::Something(val) => println!("Something is: {}", val),
-        }
+// ANCHOR: print
+fn print<T: std::fmt::Display>(val: &SomethingOrNothing<T>) {
+    match val {
+        SomethingOrNothing::Nothing => println!("Nothing."),
+        SomethingOrNothing::Something(val) => println!("Something is: {}", val),
     }
 }
+// ANCHOR_END: print
 
 // Manual implementation of [Clone]
 impl<T: Clone> Clone for SomethingOrNothing<T> {
@@ -45,10 +40,13 @@ impl<T: Copy> Copy for SomethingOrNothing<T> {}
 
 // If we remove Copy, we have a problem with the t in tab
 // in the computation of the minimum.
+// ANCHOR: minimum
 trait Minimum: Copy {
     fn min(self, rhs: Self) -> Self;
 }
+// ANCHOR_END: minimum
 
+// ANCHOR: minimum_impl
 impl<T: Minimum> Minimum for SomethingOrNothing<T> {
     fn min(self, rhs: Self) -> Self {
         match (self, rhs) {
@@ -67,6 +65,7 @@ impl<T: Minimum> Minimum for SomethingOrNothing<T> {
         }
     }
 }
+// ANCHOR_END: minimum_impl
 
 impl Minimum for i32 {
     fn min(self, rhs: Self) -> Self {
@@ -87,31 +86,37 @@ fn read_command_line() -> [i32; SIZE] {
 
 // Prints all the elements of the `tab`.
 // Tab is borrowed here
-fn print_tab(tab: &[i32; SIZE]) {
+// ANCHOR: print_tab
+fn print_tab<T: std::fmt::Display>(tab: &[T; SIZE]) {
     for t in tab {
         print!("{} ", t);
     }
     println!();
 }
+// ANCHOR_END: print_tab
 
 // Computes the minimum of a borrowed Array of a type T which implements the [Minimum] trait.
 // Returns a [SomethingOrNothing::Something] containing the the minimum value
 // or [SomethingOrNothing::Nothing] if no minimum value was found.
+// ANCHOR: find_min
 fn find_min<T: Minimum>(tab: &[T; SIZE]) -> SomethingOrNothing<T> {
-    let mut minimum = SomethingOrNothing::Nothing;
-    // Here is T is Copyable. Which means that t is not moved in the loop
+    let mut current_minimum = SomethingOrNothing::Nothing;
+    // Here is T is not Copyable tab is consumed and cannot be returned
     for t in tab {
-        minimum = minimum.min(SomethingOrNothing::Something(*t));
+        current_minimum = current_minimum.min(SomethingOrNothing::new(*t));
     }
-    minimum
+    current_minimum
 }
+// ANCHOR_END: find_min
 
+// ANCHOR: main
 fn main() {
     let tab = read_command_line();
     println!("Among the Somethings in the list:");
     print_tab(&tab);
-    // There are alternatives to access fields of tuples
     let min = find_min(&tab);
-    // The first field is not used therefore we can replace it with "_"
-    min.print();
+    print(&min);
 }
+// ANCHOR_END: main
+
+/* ANCHOR_END: all */