diff --git a/slides/fonctions_dordre_superieur.md b/slides/fonctions_dordre_superieur.md
new file mode 100644
index 0000000000000000000000000000000000000000..a0c6f522beb38b261470bafc4d6eac8d0e088713
--- /dev/null
+++ b/slides/fonctions_dordre_superieur.md
@@ -0,0 +1,277 @@
+---
+title: "Fonctions d'ordre supérieur"
+date: "2025-05-16"
+---
+
+# Tribute
+
+Rendons à Cesar:
+
+* Ces slides ont été écrits par Michaël El Kharroubi
+* J'arrive pas à changer l'auteur simplement sur un slide donc....
+* Merci à lui pour ses efforts et qu'il soit crédité comme il se doit!
+
+# Présentation du problème
+
+* Imaginons que nous ayons la structure d'un vecteur en 3 dimensions suivante
+
+```C
+typedef struct _vec3 {
+    double x;
+    double y;
+    double z;
+} vec3;
+```
+
+* On souhaite implémenter 3 opérations différentes
+    * La somme
+    * La soustraction
+    * Le produit de Hadamard (produit composantes à composantes)
+
+# Présentation du problème (suite)
+
+On a donc les fonctions suivantes
+
+* Addition
+
+```c
+vec3 add(vec3 lhs, vec3 rhs){
+    vec3 res;
+    res.x = lhs.x + rhs.x;
+    res.y = lhs.y + rhs.y;
+    res.z = lhs.z + rhs.z;
+    return res;
+}
+```
+# Présentation du problème (suite)
+
+
+* Soustraction
+```c
+vec3 sub(vec3 lhs, vec3 rhs){
+    vec3 res;
+    res.x = lhs.x - rhs.x;
+    res.y = lhs.y - rhs.y;
+    res.z = lhs.z - rhs.z;
+    return res;
+}
+```
+
+# Présentation du problème (suite)
+
+* Produit de Hadamard
+
+```c
+vec3 mul(vec3 lhs, vec3 rhs){
+    vec3 res;
+    res.x = lhs.x * rhs.x;
+    res.y = lhs.y * rhs.y;
+    res.z = lhs.z * rhs.z;
+    return res;
+}
+```
+
+* Quel est le problème avec ces trois fonctions?
+
+# Présentation du problème (suite)
+
+* Le problème avec ces fonctions c'est la **répétition**.
+* La seule chose qui change, c'est l'opérateur (+,-,*).
+* Problèmes possibles
+    * Tentation de copier-coller du code (donc risque d'erreurs)
+    * Faible résilience au changement (imaginons que je veuille des vecteurs 2d, 4d, nd)
+
+# Présentation du problème (solution)
+
+* Vecteur de taille dynamique
+
+```c
+typedef struct _vecn {
+    int size;
+    double *xs;
+} vecn;
+```
+
+* Règle le problème de résilience du code, mais ne règle pas le problème de répétition...
+
+# Fonction d'ordre supérieur (solution au problème)
+
+* Pour notre problème, nous aimerions donc découpler l'opération (opération entre deux termes : +,-,*) de l'itération sur les composantes.
+
+* Ce qui nous donne conceptuellement en pseudo c
+
+```c
+// Attention pseudo c, ne compile pas !!!!!
+vec3 apply_operator(operator op, vec3 lhs, vec3 rhs){
+    vec3 res;
+    res.x = lhs.x op rhs.x;
+    res.y = lhs.y op rhs.y;
+    res.z = lhs.z op rhs.z;
+    return res;
+}
+```
+
+# Fonction d'ordre supérieur (solution au problème)
+
+* Avec notre fonction conceptuelle `apply_operator`, on pourrait faire (toujours en pseudo c)
+
+```c
+// Attention pseudo c, ne compile pas !!!!!
+vec3 add(vec3 lhs, vec3 rhs){
+    return apply_operator(+, lhs, rhs);
+}
+vec3 sub(vec3 lhs, vec3 rhs){
+    return apply_operator(-, lhs, rhs);
+}
+vec3 mul(vec3 lhs, vec3 rhs){
+    return apply_operator(*, lhs, rhs);
+}
+```
+
+* En fait, on vient de créer ce qu'on appelle une fonction d'ordre supérieur.
+
+# Fonction d'ordre supérieur (définition)
+
+* Une fonction d'ordre supérieur est une fonction qui prend en paramètre et/ou retourne une(des) autre(s) fonction(s).  
+
+* Si on essayait de définir `operator`, c'est en fait une fonction qui prend deux paramètres (un terme de gauche et un terme de droite). On s'en aperçoit clairement avec la notation préfix (polonaise).
+    * `L + R -> + L R`
+    * `L - R -> - L R`
+    * `L * R -> * L R`
+
+* Comment l'implémenter concrètement en C?
+
+# Implémentation
+
+* Si on reprend la signature de notre fonction d'exemple, on a
+
+```c
+vec3 apply_operator(operator op, vec3 lhs, vec3 rhs);
+```
+
+* Nous avons déterminé que les `operator` étaient des fonctions qui prennaient deux paramètres.
+
+* Pour passer une fonction en paramètre en C, nous devons la passer par référence, c'est à dire à l'aide d'un pointeur de fonction.
+
+# Pointeur de fonctions
+
+* Un pointeur de fonction se définit ainsi
+
+    ```c
+    <type retour> (*<nom ptr fonc>)(<type params(s)>);
+    ```
+* Ou encore avec un `typedef`
+
+    ```c
+    typedef <type retour> (*<nom ptr fonc>)(<type params(s)>);
+    ```
+* Dans notre cas, nous avons donc un type de fonction nommé `operator`, qui prend en entrée deux `double`{.c} et qui retourne un `double`{.c}. Ce qui nous donne 
+
+    ```c
+    typedef double (*operator)(double, double);
+    ```
+
+# Implémentation (suite)
+
+* En reprenant notre fonction `apply_operator`, on a donc
+
+```c
+vec3 apply_operator(operator op, vec3 lhs, vec3 rhs){
+    vec3 res;
+    res.x = op(lhs.x, rhs.x);
+    res.y = op(lhs.y, rhs.y);
+    res.z = op(lhs.z, rhs.z);
+    return res;
+}
+```
+
+* NB : On voit que pour appeler notre fonction passée en paramètre, nous avons pu le faire comme avec n'importe quelle fonction.
+
+# Résultat
+
+```c
+typedef double (*operator)(double, double);
+vec3 apply_operator(operator op, vec3 lhs, vec3 rhs){
+    vec3 res;
+    res.x = op(lhs.x, rhs.x);
+    res.y = op(lhs.y, rhs.y);
+    res.z = op(lhs.z, rhs.z);
+    return res;
+}
+double add_dbl(double lhs, double rhs){
+    return lhs + rhs;
+}
+vec3 add(vec3 lhs, vec3 rhs){
+    return apply_operator(add_dbl, lhs, rhs);
+}
+```
+
+# Fonctions d'ordre supérieur appliquées aux tableaux
+
+* Comment appliquer des opérations sur un vecteur de taille n?
+    * Map (application d'une fonction)
+        * `add_one`, `square`
+    * Filter (discrimination selon un prédicat)
+        * `is_even`, `is_lower_than_five`
+    * Reduce (réduction d'un vecteur à un seul élément)
+        * `sum`, `multiply`
+        
+# Le map
+
+* Exemple d'application
+
+    ```c
+    typedef double (*operator)(double);
+    double *map(operator op, double *tab, size_t size) {
+        double *res = malloc(sizeof(*res) * size);
+        for (int i = 0; i < size; ++i) {
+            res[i] = op(tab[i]);
+        }
+        return res;
+    }
+    double add_one(double val) {
+        return val + 1;
+    }
+    double sqr(double val){
+        return val * val;
+    }
+    double tab[] = {1.0, 2.0, 3.0};
+    double *square = map(sqr, tab, 3);
+    double *and_one = map(add_one, square, 3);
+    ```
+
+# Le map
+
+* Permettrait le chaînage.
+
+    ```C
+    double *sqr_and_one = map(add_one, map(sqr, tab, 3), 3);
+    ```
+. . .
+
+* Problème?
+
+. . .
+
+* Allocation dynamique... fuite mémoire.
+
+. . .
+
+* Solution?
+
+. . .
+
+    ```c
+    typedef double (*operator)(double);
+    double *map(operator op, double *tab, size_t size) {
+        double *res = malloc(sizeof(*res) * size);
+        for (int i = 0; i < size; ++i) {
+            res[i] = op(tab[i]);
+        }
+        free(tab);
+        return res;
+    }
+    ```
+
+* Problème potentiel?
+* **Attention au double free!**
diff --git a/slides/genericite.md b/slides/genericite.md
new file mode 100644
index 0000000000000000000000000000000000000000..6d9101baff9f5e4395d89d58595a4fa081a7ecaf
--- /dev/null
+++ b/slides/genericite.md
@@ -0,0 +1,180 @@
+---
+title: "La généricité"
+date: "2025-05-16"
+---
+
+# Problématique
+
+* En C on doit écrire chaque algorithme/structures de données pour des types
+  précis (`int`, `double`, `char`, ...).
+
+    ```
+    void int_sort(int size, int tab[size]);    // tri d'entiers
+    void double_sort(int size, int tab[size]); // tri de double
+    void char_sort(int size, char tab[size]);  // tri de char
+    ```
+* Duplication du code pour chaque type possible et imaginable.
+* On aimerait un moyen pour pouvoir représenter "n'importe quel type" sans
+  réécrire tout le code.
+
+# La généricité
+
+## Une "solution": `void *`{.C}
+
+* En général, un pointeur connaît son **adresse** et le **type** des données sur lesquelles il pointe.
+ 
+    ```C
+    int *a = malloc(sizeof(*a));
+    int *b = malloc(sizeof(int));
+    ```
+* Un `void *`{.C} le connaît **que** son adresse, au programmeur de pas faire n'importe quoi.
+* Vous avez déjà utilisé des fonctions utilisant des `void *`{.C}
+ 
+    ```C
+    void *malloc(size_t size);
+    void free(void *);
+    ```
+
+# Attention danger
+
+* Ne permet pas au compilateur de vérifier les types.
+* Les données pointées n'ayant pas de type, il faut déréférencer avec précaution:
+  
+    ```C
+    int a = 2;
+    void *b = &a; //jusqu'ici tout va bien
+    double c = *b; // argl!
+    ```
+* Une attention accrue est nécessaire.
+
+# Cas particuier: on sait pas comment libérer la mémoire
+
+## Exemple
+
+```C 
+struct tab {
+    int *t;
+}
+struct tab *tmp = malloc(sizeof(*tmp));
+tmp->t = malloc(10 * sizeof(*(tmp->t)));
+free(tmp); // memory leak of tmp->t...
+```
+
+. . .
+
+## Solution: tout faire à la main
+
+```C 
+free(tmp->t);
+free(tmp);
+```
+
+# Exemple simple
+
+* On souhaite échanger deux pointeurs
+
+    ```C 
+    int *a = malloc();
+    int *b = malloc();
+    swap(&a, &b);
+    ```
+* Comment écrire `swap()` pour que le code ci-dessus marche pour n'importe quel
+  type?
+
+. . .
+
+```C 
+void swap(void **a, void **b) {
+    void *tmp = *a;
+    *a = *b;
+    *b = tmp;
+}
+```
+
+
+
+# Cas d'utilisation (1/4)
+
+\footnotesize
+
+* La somme d'un tableau de type arbitraire (facile non?)
+
+    ```C
+    void sum(void *tab, int length, size_t size_elem, void *zero,
+        void (*add)(void *, void *)) {
+        for (int i = 0; i < length; ++i) {
+            void *rhs = (void *)((char *)tab + i * size_elem);
+            add(zero, rhs);
+        } // de combien on "saute" avec un void *?
+    }
+    ```
+* Pour des entiers
+
+    ```C 
+    void int_add(void *lhs, void *rhs) {
+        *((int *)lhs) += *((int *)rhs); // cast d'entiers
+    }
+    int zero  = 0;
+    int tab[] = {1, -2, 4, 5};
+    sum(tab, 4, sizeof(int), &zero, int_add);
+    printf("%d\n", zero);
+    ```
+
+# Cas d'utilisation (2/4)
+
+## Que fait cette fonction?
+
+\footnotesize
+
+```C
+void *foo(void *tab, int n_items, int s_items, 
+          bool (*bar)(void *, void *)) {
+    if (n_items <= 0 || s_items <= 0 || NULL == tab) {
+        return NULL;
+    }
+    void *elem = tab;
+    for (int i = 1; i < n_items; ++i) {
+        // void pointer arithmetics is illegal in C 
+        // (gcc is ok though)
+        void *tmp_elem = (void *)((char *)tab + i*s_items);
+
+        if (bar(elem, tmp_elem)) {
+            elem = tmp_elem;
+        }
+    }
+    return elem;
+}
+```
+
+# Cas d'utilisation (3/4)
+
+## Avec un tableau de `int`{.C}
+
+```C
+bool cmp_int(void *a, void *b) {
+    return (*(int *)a < *(int *)b);
+}
+
+int main() {
+    int tab[] = {-1, 2, 10, 3, 8};
+    int *a = foo(tab, 5, sizeof(int), cmp_int);
+    printf("a = %d\n", *a);
+}
+```
+
+# Cas d'utilisation (4/4)
+
+## Avec un tableau de `double`{.C}
+
+```C
+bool cmp_dbl(void *a, void *b) {
+    return (*(double *)a < *(double *)b);
+}
+
+int main() {
+    double tab[] = {-1.2, 2.1, 10.5, 3.6, 18.1};
+    double *a = foo(tab, 5, sizeof(double), cmp_dbl);
+    printf("a = %f\n", *a);
+}
+```
+