ajout chapitre paradigme
This commit is contained in:
252
Paradigmes/README.md
Normal file
252
Paradigmes/README.md
Normal file
@@ -0,0 +1,252 @@
|
||||
## Paradigmes de programmation
|
||||
|
||||
> Un paradigme est à la programmation ce qu’un style culinaire est à la cuisine : il impose des règles, des outils, et une manière de faire.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
------
|
||||
|
||||
### Introduction
|
||||
|
||||
En programmation, il n’existe pas qu’une seule bonne façon de penser. Comme pour résoudre un problème de maths ou construire une maison, plusieurs approches sont possibles. Ces manières de faire s’appellent des ***paradigmes***.
|
||||
|
||||
On appelle paradigme une méthode de programmation.
|
||||
|
||||
On peut regrouper les différents paradigmes en 2 catégories :
|
||||
|
||||
- la programmation **impérative** ;
|
||||
- la programmation **déclarative**.
|
||||
|
||||
Lorsque l'on utilise la programmation impérative, on décrit le comment / la solution. On la retrouve dans plusieurs langage :
|
||||
|
||||
- Structurée (FORTRAN, C)
|
||||
- Procédurale (FORTRAN, C)
|
||||
- Objet (C++, Java, Python)
|
||||
- Modulaire (C++, Java, Python)
|
||||
|
||||
Lorsque l'on utilise la programmation déclarative, on décrit le quoi / le problème. On la retrouve dans plusieurs langage :
|
||||
|
||||
- Descriptif (HTML, SQL)
|
||||
- Fonctionnel (LISP, CAML)
|
||||
- Logique (Prolog, SQL)
|
||||
|
||||
-------
|
||||
|
||||
### Programmation fonctionnelle
|
||||
|
||||
#### Les différences
|
||||
|
||||
La programmation impérative, bien que versatile, conduit rapidement à des programmes difficiles à comprendre et à maintenir, où la démonstration de la correction est impossible.
|
||||
|
||||
Ceci est du au fait qu’un traitement de données :
|
||||
|
||||
- dépend de paramètres extérieurs non maîtrisés : variables ;
|
||||
- modifie les données, ou d’autres : affectation ;
|
||||
- réalise une tâche complexe : une fonction complexe.
|
||||
|
||||
```
|
||||
a = 3
|
||||
|
||||
répéter 5 fois :
|
||||
a = a + 2
|
||||
|
||||
afficher a
|
||||
```
|
||||
|
||||
|
||||
|
||||
La programmation fonctionnelle pure s’absout de ces problèmes :
|
||||
|
||||
- pas de variables
|
||||
- pas d’affectation
|
||||
- enchaînement de fonctions simples.
|
||||
|
||||
```
|
||||
f : x -> x + 2
|
||||
|
||||
afficher f(f(f(f(f(3)))))
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### Le principe
|
||||
|
||||
Le but d'un traitement informatique est de produire des données à partir de données.
|
||||
|
||||
Le programme est une une fonction qui associe des données sortantes à des données entrantes.
|
||||
|
||||
```
|
||||
f : données entrantes -> données sortantes
|
||||
Pas d'état interne
|
||||
Les données sont non mutables
|
||||
```
|
||||
|
||||
Un traitement complexe s'obtiendra en composant plusieurs fonctions intermédiaires simples et une boucle s’obtiendra par une fonction qui s’appelle elle-même : **récursion**.
|
||||
|
||||
En clair : **__La variable n'existe pas !__**.
|
||||
|
||||
#### Avantages et les inconvénients
|
||||
|
||||
Pour les avantages :
|
||||
|
||||
- Absence d’effets de bord.
|
||||
- Toute fonction fournit un résultat prédictible qui est toujours le même.
|
||||
- Clarifie l’interprétation du programme et facilite sa correction.
|
||||
- Évite l’apparition de bugs non prédictibles.
|
||||
|
||||
En revanche, on retrouve des inconvénients :
|
||||
|
||||
- Un traitement classique nécessite un grand nombre de fonctions.
|
||||
- Nuit au développement de grosses applications.
|
||||
- Gourmand en ressources (stockage des résultats intermédiaires, pile des appels récursifs).
|
||||
- Certaines fonctions doivent pouvoir modifier des données extérieures, ou en dépendre.
|
||||
|
||||
#### Effets de bord
|
||||
|
||||
Une fonction à effet de bord est une fonction qui modifie ou utilise une variable extérieure à son environnement local (variables globales, opérations d’entrées/sorties).
|
||||
|
||||
**__À n’utiliser que lorsque cela est nécessaire !__**
|
||||
|
||||
Les effets de bord peuvent être évité facilement grâce au principe de localité des variables et la programmation fonctionnelle.
|
||||
|
||||
```python
|
||||
# Fonction avec effets de bord :
|
||||
|
||||
def ajoute_k_a_n(k):
|
||||
global n
|
||||
n = n + k
|
||||
return n
|
||||
|
||||
n = 2
|
||||
print("Avec k=2 : ", ajoute_k_a_n(2))
|
||||
print("Avec k=3 : ", ajoute_k_a_n(3))
|
||||
```
|
||||
|
||||
```python
|
||||
# Fonction sans effets de bord :
|
||||
|
||||
def ajoute_k_a_n(n, k):
|
||||
return n + k
|
||||
|
||||
print("Avec k=2 : ", ajoute_k_a_n(2))
|
||||
print("Avec k=3 : ", ajoute_k_a_n(3))
|
||||
```
|
||||
|
||||
#### Fonctions lambdas
|
||||
|
||||
λ-calcul (années 1930) : système formel inventé par Alonzo Church fonde les concepts de fonction et d'application premier formalisme qui définit et caractérise les fonctions récursives.
|
||||
|
||||
```lambda : x -> expression(x)```
|
||||
|
||||
Tout comme la machine de Turing, le λ-calcul peut représenter n’importe quel calcul (hypothèse de Church-Turing, chaque approche peut être exprimée dans l’autre).
|
||||
|
||||
La programmation **fonctionnelle** puise son origine du __λ-calcul__ alors que la programmation **impérative** puise son origine de la __machine de Turing__.
|
||||
|
||||
En python la lambda fonction se définie à l'aide du mot clé **lambda** :
|
||||
|
||||
```python
|
||||
add_a_b = lambda a,b: a + b
|
||||
|
||||
entre_10_et_20 = lambda x : True if (x > 10 and x < 20) else False
|
||||
```
|
||||
|
||||
Appelée aussi fonction anonyme, il ne faut pas en abuser en Python, elle :
|
||||
|
||||
- est utile pour définir une fonction simple, proche d’une définition mathématique, en une ligne ;
|
||||
- est utile pour créer la fonction de sortie d’une fonction d’ordre supérieur ;
|
||||
- est utile pour composer les fonctions ;
|
||||
- peut utiliser les mots clés if et else ;
|
||||
- peut s’utiliser avec les fonctions d’ordres supérieur (exemple du tri de Python) ;
|
||||
- peut s’utiliser conjointement à la compréhension de listes.
|
||||
|
||||
#### Fonctions et listes
|
||||
|
||||
__Le mapping__
|
||||
|
||||
Appliquer une fonction à chaque élément d'une liste.
|
||||
|
||||
```python
|
||||
f = lambda x: x*5
|
||||
liste = [2, 7, -1]
|
||||
resultat = map(f, liste)
|
||||
```
|
||||
|
||||
__La réduction__
|
||||
|
||||
Combiner les éléments d’une liste en appliquant une fonction à l’aide d’un accumulateur (à l’état initial, acc prend la première valeur de la liste et x la deuxième, le résultat est stocké dans acc).
|
||||
|
||||
```python
|
||||
liste = [1, 3, 5, 6, 2]
|
||||
f_somme = lambda acc, x: acc + x
|
||||
somme = functools.reduce(f_somme, liste)
|
||||
```
|
||||
|
||||
```python
|
||||
liste = [1, 3, 5, 6, 2]
|
||||
f_maximum = lambda acc, x: acc if acc > x else x
|
||||
maximum = functools.reduce(f_maximum, liste)
|
||||
```
|
||||
|
||||
__Le filtrage__
|
||||
|
||||
Sélection les éléments d’une liste vérifiant un certain critère.
|
||||
|
||||
```python
|
||||
liste = [1, 3, 5, 6, 2]
|
||||
f_filtre = lambda x: x >= 3
|
||||
liste_filtree = filter(f_filtre, liste)
|
||||
```
|
||||
|
||||
#### Boucler en programmation fonctionnelle
|
||||
|
||||
On utilise la récursion, la fonction s’appelant elle-même un certain nombre de fois.
|
||||
|
||||
```python
|
||||
def ajoute_5(n, x):
|
||||
if n == 0:
|
||||
return x
|
||||
else:
|
||||
return ajoute_5(n - 1, x + 5)
|
||||
|
||||
resultat = ajoute_5(3, 2)
|
||||
print(resultat)
|
||||
```
|
||||
|
||||
On peut aussi plus simplement appliquer une réduction sur une liste de *n* éléments.
|
||||
|
||||
```python
|
||||
ajoute_5 = lambda acc, x: acc + 5
|
||||
resultat = functools.reduce(ajoute_5, range(3), 2) # avec 2 pour valeur initiale de l'accumulateur
|
||||
print(resultat)
|
||||
```
|
||||
|
||||
----------------
|
||||
|
||||
#### Exemples de langages multi-paradigmes
|
||||
|
||||
- Python : impératif, objet, fonctionnel
|
||||
- JavaScript : impératif, objet, fonctionnel
|
||||
- Scala : objet + fonctionnel
|
||||
- Rust : impératif + fonctionnel
|
||||
|
||||
----------
|
||||
|
||||
### Exercice
|
||||
|
||||
Voici une tâche simple : nous voulons faire cuire des pâtes.
|
||||
|
||||
Écrire la recette sous forme de code python :
|
||||
|
||||
- **Version impérative : liste d’instructions étape par étape.**
|
||||
- **Version fonctionnelle : une fonction pure qui prend un état (pâtes non cuites) et retourne un nouvel état (pâtes cuites).**
|
||||
- **Version orientée objet : crée une classe **Pates *avec une méthode* cuire().
|
||||
|
||||
------
|
||||
|
||||
Auteurs : Florian Mathieu, Timothée Decoster, Enzo Frémaux
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
BIN
Paradigmes/assets/bo.png
Normal file
BIN
Paradigmes/assets/bo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
Reference in New Issue
Block a user