Skip to content
Snippets Groups Projects
Verified Commit 25d9eb89 authored by orestis.malaspin's avatar orestis.malaspin
Browse files

updated fos

parent f9023c36
No related branches found
No related tags found
No related merge requests found
---
title: "Fonctions d'ordre supérieur"
date: "2023-03-21"
---
# 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.
# Rappel pointeur de fonctions
* Un pointeur de fonction se définit ainsi
```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`
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment