Transparence référentielleLa transparence référentielle est une propriété des expressions d'un langage de programmation qui fait qu'une expression peut être remplacée par sa valeur sans changer le comportement du programme. Définition
Si toutes les fonctions impliquées dans l'expression sont pures, c'est-à-dire si elles ont toujours les mêmes valeurs de retour pour les mêmes arguments et si elles sont sans effets de bord, alors l'expression est référentiellement transparente. Mais la réciproque est fausse : une expression référentiellement transparente peut impliquer des fonctions impures. La transparence référentielle est la pierre angulaire de la programmation fonctionnelle. Elle permet notamment la mémoïsation des fonctions référentiellement transparentes (c'est-à-dire la mémorisation des valeurs précédemment calculées). Exemples et contre-exemplesLes opérations arithmétiques sont référentiellement transparentes :
on peut ainsi remplacer En revanche, l'expression Contraste avec la programmation impérativeSi la substitution d'une expression par sa valeur est valide seulement à certains points d'un programme, alors l'expression n'est pas référentiellement transparente. La définition et l'ordre de ses points de séquence (en) sont la fondation théorique de la programmation impérative, et une porte de la sémantique des langages de programmation impératifs.[pas clair] Néanmoins, puisqu'une expression référentiellement transparente peut toujours être remplacée par sa valeur ou par une expression produisant la même valeur, il n'est pas nécessaire de définir des points de séquence ou de préserver l'ordre d'évaluation. On appelle programmation purement fonctionnelle un paradigme de programmation exempt des soucis d'un ordonnancement figé des exécutions. L'avantage d'écrire du code référentiellement transparent est que l'analyse de code statique est plus facile et que des transformations automatiques d'amélioration de code sont possibles. Par exemple, en programmation en C, inclure une fonction dans une boucle se paye en matière de performances, alors que cette fonction pourrait être déplacée hors de la boucle sans changer les résultats du programme. En déplaçant cette fonction, le programmeur peut y perdre en lisibilité du code. Mais, si le compilateur est capable de déterminer la transparence référentielle de l'appel de la fonction, il effectuera automatiquement ce déplacement produisant ainsi du code plus efficace. Les langages imposant la transparence référentielle rendent malaisée l'écriture d'opérations qui s'expriment naturellement comme une suite de pas. De tels langages peuvent incorporer des mécanismes pour rendre ces tâches plus faciles tout en retenant leur qualité purement fonctionnelle telles que les monades et les definite clause grammars. Alors qu'en mathématiques toutes les applications de fonction sont référentiellement transparentes, en programmation impérative ça n'est pas toujours le cas. Par exemple dans le cas d'une fonction sans paramètre qui retourne une chaîne saisie au clavier, la valeur de retour dépend de la valeur saisie, donc de multiples appels de la fonction avec des paramètres identiques (la liste vide) peuvent retourner des résultats différents. Un appel à une fonction qui utilise une variable globale, ou une variable avec une portée dynamique ou lexicale pour aider à calculer ses résultats, n'est pas référentiellement transparente. Puisque cette variable n'est pas passée comme paramètre mais peut être altérée, les résultats des appels suivants à la fonction peuvent différer même si les paramètres sont identiques. Dans les langages fonctionnels purs, l'affectation n'est pas autorisée, en revanche l'utilisation de monades permet une programmation fonctionnelle pure tout en ayant un mécanisme qui ressemble de près aux variables globales[1]. L'importance de la transparence référentielle est qu'elle permet au programmeur ou au compilateur de raisonner sur le comportement du programme. Cela peut aider à prouver qu'il est correct, à trouver des bogues qui ne peuvent être trouvées par des tests, à simplifier un algorithme, à aider à modifier du code sans le casser, à optimiser le code par le moyen de la mémorisation ou éliminer des sous-expressions communes. Certains langages de programmation fonctionnelle (comme Haskell) imposent la transparence référentielle pour toutes les fonctions. Principe de séparation commande-requêteEiffel, bien que basé sur la programmation impérative, impose une séparation stricte entre les commandes qui peuvent produire des effets de bord et les requêtes qui doivent être référentiellement transparentes. Les requêtes retournent un résultat mais ne changent pas l'environnement. On appelle cette règle le principe de séparation commande-requête qui permet d'aboutir à un style qui sépare clairement les parties référentiellement transparentes des autres. Par exemple dans la manipulation de listes : my_list.finish -- Déplace le curseur à la fin de la liste value := my_list.item -- Obtient la valeur à la position du curseur : référentiellement transparent Cela affecte même des fonctionnalités impératives comme les entrées : my_file.read_integer -- obtient le prochain entier; effet de bord, mais pas de valeur de retour value := my_file.last_integer -- obtient le dernier entier lu: réferentiellement transparent Appeler plusieurs fois en série Autre exempleSoit deux fonctions, dont l'une globalValue = 0; integer function rq(integer x) begin globalValue = globalValue + 1; return x + globalValue; end integer function rt(integer x) begin return x + 1; end Dire que Voir aussi
Références
|