Files
TermNSI/Paradigmes
2025-04-27 22:34:40 +02:00
..
2025-04-25 09:53:59 +02:00
2025-04-27 22:34:40 +02:00

Paradigmes de programmation

Un paradigme est à la programmation ce quun style culinaire est à la cuisine : il impose des règles, des outils, et une manière de faire.

bo


Introduction

En programmation, il nexiste pas quune 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 sappellent 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 quun traitement de données :

  • dépend de paramètres extérieurs non maîtrisés : variables ;
  • modifie les données, ou dautres : 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 sabsout de ces problèmes :

  • pas de variables
  • pas daffectation
  • 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 sobtiendra par une fonction qui sappelle elle-même : récursion.

En clair : La variable n'existe pas !.

Avantages et les inconvénients

Pour les avantages :

  • Absence deffets de bord.
  • Toute fonction fournit un résultat prédictible qui est toujours le même.
  • Clarifie linterprétation du programme et facilite sa correction.
  • Évite lapparition 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 dentrées/sorties).

À nutiliser 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.

# 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))
# 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 nimporte quel calcul (hypothèse de Church-Turing, chaque approche peut être exprimée dans lautre).

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 :

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 dune définition mathématique, en une ligne ;
  • est utile pour créer la fonction de sortie dune fonction dordre supérieur ;
  • est utile pour composer les fonctions ;
  • peut utiliser les mots clés if et else ;
  • peut sutiliser avec les fonctions dordres supérieur (exemple du tri de Python) ;
  • peut sutiliser conjointement à la compréhension de listes.

Fonctions et listes

Le mapping

Appliquer une fonction à chaque élément d'une liste.

f = lambda x: x*5
liste = [2, 7, -1]
resultat = map(f, liste)

La réduction

Combiner les éléments dune liste en appliquant une fonction à laide dun 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).

liste = [1, 3, 5, 6, 2]
f_somme = lambda acc, x: acc + x
somme = functools.reduce(f_somme, liste)
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 dune liste vérifiant un certain critère.

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 sappelant elle-même un certain nombre de fois.

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.

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 dinstructions é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éer une classe Pates avec une méthode cuire().

Auteurs : Florian Mathieu, Timothée Decoster, Enzo Frémaux

Licence CC BY NC

Licence Creative Commons
Ce cours est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas dUtilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.