Skip to content
Snippets Groups Projects

Ajout slides fonctions d'ordre supérieur.

Merged Michaël El Kharroubi requested to merge high-order-functions into master
All threads resolved!
1 file
+ 3
3
Compare changes
  • Side-by-side
  • Inline
+ 215
0
 
---
 
author: "Michaël El Kharroubi (A403), ISC, HEPIA"
 
institute: ""
 
title: "Fonctions d'ordre supérieur"
 
date: "2022-02-22"
 
patat:
 
wrap: true
 
margins:
 
left: 10
 
right: 10
 
---
 
 
# 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`
 
 
\ No newline at end of file
Loading