> 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.
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écursivité**.
- 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.
λ-calcul (années 1930) : un système formel inventé par Alonzo Church qui fonde les concepts de fonction et d'application. Il s'agit du premier formalisme qui définit et caractérise les fonctions récursives.
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)elseFalse
```
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.
<arel="license"href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><imgalt="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 <arel="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>.