Programmation fonctionnelle

publicité
Concepts des langages de
programmation
Programmation fonctionnelle
Plan
Introduction
Principes de la programmation fonctionnelle
Concepts de la programmation fonctionnelle
Applications des langages fonctionnels
Comparaison des langages fonctionnels et impératifs
2
Introduction
La conception des langages de programmation impératifs
est principalement basée sur l'architecture de von
Neumann (à base de registres)
Conception liée à l'architecture des machines
La conception des langages fonctionnels est basée sur les
fonctions mathématiques
Une base théorique solide qui est proche de l'utilisateur mais
non liée à l'architecture des machines sur lesquelles les
programmes vont s'exécuter
Tout programme dans les langages fonctionnels est vu
comme une fonction mathématique
3
Principes de la programmation
fonctionnelle
Les programmes doivent se comporter comme des
fonctions mathématiques
Étant donné un ensemble d’entrée, la fonction devrait
retourner toujours les mêmes valeurs
Ce qui signifie que les fonctions ne sauvegardent pas
d’état entre deux appels
4
Fonctions sans états
Convient parfaitement au monde de la programmation
concurrente
Concepts de la programmation
fonctionnelle
Fonctions mathématiques
Fonctions lambda
Fonctions d'ordre supérieur
Composition de fonctions
Appliquer-à-tout
Transparence référentielle
Interfaçage
Évaluation paresseuse
5
Fonctions mathématiques
Une fonction mathématique est une mise en correspondance
des éléments d'un ensemble, appelé domaine, aux éléments
d'un autre ensemble appelé image ou co-domaine
Le domaine de la fonction correspond aux données fournies au
programme ("l'entrée")
L'image de la fonction correspond aux données produites par le
programme ("la sortie")
Exemple
Fonction : somme(x,y) = x+y
somme(2,3) = 5
6
2 et 3 constituent l'entrée de la fonction somme (paramètres d'entrée) et 5
constitue la sortie (résultat)
Les expressions Lambda
Une expression lambda spécifie les paramètres et la mise en
correspondance d'une fonction dans la forme ci-dessous :
λ(x) x * x * x
Est équivalent à la déclaration : cube(x) = x * x * x
7
Les expressions Lambda (suite)
Les expressions Lambda décrivent des fonctions
anonymes (fonctions sans noms)
F(x) = x*x+ 10 => fonction nommée
λ(x) x*x+ 10 => fonction anonyme
Les expressions Lambda sont appliquées aux paramètres
placés après l'expression
Exemple :
8
(λ(x) x * x * x)(2)
Sera évaluée à 8 (2*2*2)
Fonction d'ordre supérieur
Une fonction d'ordre supérieur, ou forme fonctionnelle,
est une fonction qui accepte en paramètres des fonctions
ou retourne une fonction en résultat ou bien les deux
9
Composition de fonctions
La composition de fonction, est une fonction d'ordre
supérieur qui accepte deux fonctions en paramètres et
retourne une fonction en sortie
Forme :
Ce qui signifie :
h ≡ f ° g
h(x) ≡ f ( g ( x))
Pour f(x) ≡ x + 2 et g(x) ≡ 3 * x,
h ≡ f ° g donne : (3 * x)+ 2
10
Appliquer-à-tout (Apply-to-all)
Une fonction d'ordre supérieur qui accepte une seule
fonction en tant que paramètre et retourne comme
résultat une liste de valeurs obtenues de l'application de
cette fonction à chaque élément d'une liste de
paramètres
Forme : α
Exemple
Pour : h(x) ≡ x * x,
11
α( h, (2, 3, 4)) retournera : (4, 9, 16)
Transparence référentielle
Dans la programmation fonctionnelle, l'évaluation d'une
fonction produit toujours les mêmes résultats pour les
mêmes paramètres
Résultat reste le même lorsqu'on change une expression par
une autre expression de valeur égale
Ce principe est entre autres, pratique pour :
Faciliter la transformation de programmes
Exemple :
12
Les rendre plus lisibles, plus simple, améliorer les performance ou la
compilation
Une règle qui dit : x + x = 2 * x permet de remplacer f(y) + f(y) par 2
* f(y)
Transparence référentielle (suite)
La programmation impérative viole la transparence
référentielle à cause des effets de bords de quelques
fonctionnalités (exemple : affectations et changement du
contenu de fichiers)
Exemple
13
n=1
def f(x)
n +=1
return n * x
end
f(x) + f(x) est différent de 2 * f(x)
Conséquences de la transparence
référentielle
La valeur d’une expression dépend seulement de la
valeur de ses sous-expressions (exemple : la valeur de E1
+ E2 dépend seulement de la valeur de E1 et de E2, et la
valeur de E2 n’est pas influencée par E1, et vice versa)
L’ordre d’exécution a beaucoup moins d’importance
qu’en programmation impérative (E1 peut être évaluée
avant, après ou pendant l’évaluation de E2)
14
Ce qui rend la programmation fonctionnelle bien adaptée à la
programmation concurrente
Interfaçage (Currying)
Adaptation d'une fonction à un usage particulier
Exemple
Calcul de la puissance :
Adaptation de la fonction puissance pour le calcul du carré :
15
def puissance(i, j)
I ** j
end
def carre(i)
puissance(I,2)
end
Évaluation paresseuse (Lazy evaluation)
Problème :
Solution :
Dans la programmation impérative, une fonction est exécutée
dés qu'elle est appelée
La valeur de la fonction peut ne pas être utilisée
L'exécution de la fonction est donc inutile
Les langages fonctionnels proposent la possibilité d'utiliser une
évaluation (exécution) paresseuse des fonctions
Principe de l'évaluation paresseuse : n'évaluer une
fonction qu'au moment où sa valeur sera utilisée
16
Évaluation paresseuse (suite)
Exemple en Scala :
Fonction Fibonacci :
Affectation de la (valeur de la) fonction à une variable
Console.println(a) // => Lazy(?)
Utilisation de a :
17
var a = lazy({ fib(42) })
Tentative d'affichage de a (la valeur n'est pas calculée) :
def fib(n: int): int = n match {
case 0 => 0
case 1 => 1
case _ => fib(n-1)+fib(n-2)
}
a+1 // => 267914297
Application des langages fonctionnels
Les langages fonctionnels sont utilisés pour
18
La représentation des connaissances
L'apprentissage machine
Traitement des langues naturels
Modélisation de la parole et de la vision
Programmation concurrente
…
Programmation fonctionnelle vs.
programmation impérative
Langages impératifs
Exécution efficace
La concurrence est la responsabilité du programmeur
Quelques langages impératifs inclus des fonctionnalités des langages
fonctionnels (exemple : Ruby,…)
Langages fonctionnels
Exécution pas très efficace
Facilité de débogage :
Les programmes peuvent facilement être rendus concurrents :
19
une erreur peut être reproduite facilement car le bug ne dépend pas du chemin
d'exécution (ne dépend pas du code précédent le code ayant généré l'erreur)
grâce à la non sauvegarde d'état dans les fonctions : l'exécution d'une fonction par
un thread x ou un thread y n'a pas d'importance et donnera toujours le même
résultat
Quelques langages fonctionnels inclus des fonctionnalités des langages
impératifs (ex. LISP, Scala, …)
Résumé
Les langages de programmation fonctionnelle utilise des
fonctions pour contrôler l'exécution des programmes à la
place des variables et des affectations qui sont utilisées dans
les langages de programmation impérative
Les langages de programmation fonctionnels pures ont
quelques avantages sur les langages de programmation
impératifs. Cependant, ils sont moins efficaces sur les machines
existantes dont l'architecture est plus adaptée aux langages de
programmation impératifs
20
Téléchargement