* 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
vec3add(vec3lhs,vec3rhs){
vec3res;
res.x=lhs.x+rhs.x;
res.y=lhs.y+rhs.y;
res.z=lhs.z+rhs.z;
returnres;
}
```
# Présentation du problème (suite)
* Soustraction
```c
vec3sub(vec3lhs,vec3rhs){
vec3res;
res.x=lhs.x-rhs.x;
res.y=lhs.y-rhs.y;
res.z=lhs.z-rhs.z;
returnres;
}
```
# Présentation du problème (suite)
* Produit de Hadamard
```c
vec3mul(vec3lhs,vec3rhs){
vec3res;
res.x=lhs.x*rhs.x;
res.y=lhs.y*rhs.y;
res.z=lhs.z*rhs.z;
returnres;
}
```
* 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
typedefstruct_vecn{
intsize;
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 !!!!!
vec3apply_operator(operatorop,vec3lhs,vec3rhs){
vec3res;
res.x=lhs.xoprhs.x;
res.y=lhs.yoprhs.y;
res.z=lhs.zoprhs.z;
returnres;
}
```
# 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 !!!!!
vec3add(vec3lhs,vec3rhs){
returnapply_operator(+,lhs,rhs);
}
vec3sub(vec3lhs,vec3rhs){
returnapply_operator(-,lhs,rhs);
}
vec3mul(vec3lhs,vec3rhs){
returnapply_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
vec3apply_operator(operatorop,vec3lhs,vec3rhs);
```
* 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
<typeretour>(*<nomptrfonc>)(<typeparams(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
typedefdouble(*operator)(double,double);
```
# Implémentation (suite)
* En reprenant notre fonction `apply_operator`, on a donc
```c
vec3apply_operator(operatorop,vec3lhs,vec3rhs){
vec3res;
res.x=op(lhs.x,rhs.x);
res.y=op(lhs.y,rhs.y);
res.z=op(lhs.z,rhs.z);
returnres;
}
```
* NB : On voit que pour appeler notre fonction passée en paramètre, nous avons pu le faire comme avec n'importe quelle fonction.