Skip to content
Snippets Groups Projects
Commit 5e5bd996 authored by Michaël El Kharroubi's avatar Michaël El Kharroubi :satellite: Committed by orestis.malaspin
Browse files

Ajout slides fonctions d'ordre supérieur.

parent cf86f163
No related branches found
No related tags found
No related merge requests found
...@@ -26,13 +26,13 @@ all: $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.html et % ...@@ -26,13 +26,13 @@ all: $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.html et %
markdown: $(MARKDOWN) # La markdown les cibles %.markdown markdown: $(MARKDOWN) # La markdown les cibles %.markdown
%.pdf: %.md metadata.yaml # %.pdf (chaque fichier %.md génère un fichier avec le même nom mais l'extension .pdf et la dépendance metadata.yaml) %.pdf: metadata.yaml %.md # %.pdf (chaque fichier %.md génère un fichier avec le même nom mais l'extension .pdf et la dépendance metadata.yaml)
pandoc -s $(OPTIONS) $(PDFOPTIONS) -o $@ $^ pandoc -s $(OPTIONS) $(PDFOPTIONS) -o $@ $^
%.html: %.md metadata.yaml %.html: metadata.yaml %.md
pandoc -s $(OPTIONS) $(REVEALOPTIONS) -o $@ $^ pandoc -s $(OPTIONS) $(REVEALOPTIONS) -o $@ $^
%.markdown: %.md metadata.yaml yq %.markdown: metadata.yaml %.md yq
sed '1 { /^---/ { :a N; /\n---/! ba; d} }' $< > no_header sed '1 { /^---/ { :a N; /\n---/! ba; d} }' $< > no_header
grep -v -F -x -f no_header $< > header.yaml grep -v -F -x -f no_header $< > header.yaml
echo "---" > tmp.yaml echo "---" > tmp.yaml
......
---
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
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