Que signifie le terme transparence référentielle ? Je l'ai entendu décrit comme «cela signifie que vous pouvez remplacer des égaux par des égaux», mais cela semble être une explication inadéquate.
285
Que signifie le terme transparence référentielle ? Je l'ai entendu décrit comme «cela signifie que vous pouvez remplacer des égaux par des égaux», mais cela semble être une explication inadéquate.
Réponses:
Le terme «transparence référentielle» vient de la philosophie analytique , la branche de la philosophie qui analyse les constructions, les déclarations et les arguments du langage naturel basés sur les méthodes de la logique et des mathématiques. En d'autres termes, c'est le sujet le plus proche en dehors de l'informatique de ce que nous appelons la sémantique du langage de programmation . Le philosophe Willard Quine était responsable de l'initiation du concept de transparence référentielle, mais il était également implicite dans les approches de Bertrand Russell et Alfred Whitehead.
À la base, la "transparence référentielle" est une idée très simple et claire. Le terme «référent» est utilisé en philosophie analytique pour parler de la chose à laquelle une expression fait référence . C'est à peu près la même chose que ce que nous entendons par «sens» ou «dénotation» dans la sémantique du langage de programmation. En utilisant l'exemple d'Andrew Birkett ( article de blog ), le terme «la capitale de l'Écosse» fait référence à la ville d'Édimbourg. C'est un exemple simple de "référent".
Un contexte dans une phrase est "référentiellement transparent" si le remplacement d'un terme dans ce contexte par un autre terme qui fait référence à la même entité ne change pas le sens. Par exemple
signifie la même chose que
Le contexte "Le Parlement écossais se réunit dans ..." est donc un contexte référentiellement transparent. Nous pouvons remplacer «la capitale de l'Écosse» par «Édimbourg» sans en altérer le sens. En d'autres termes, le contexte ne se soucie que de ce à quoi le terme fait référence et de rien d'autre. C'est dans ce sens que le contexte est «référentiellement transparent».
D'un autre côté, dans la phrase,
nous ne pouvons pas faire un tel remplacement. Si nous le faisions, nous obtiendrions "Édimbourg est Édimbourg depuis 1999", ce qui est une chose folle à dire, et ne donne pas le même sens que la phrase d'origine. Il semblerait donc que le contexte "Édimbourg a été ... depuis 1999" est référentiellement opaque (l'opposé de référentiellement transparent). Il se soucie apparemment de quelque chose de plus que ce à quoi le terme fait référence. Qu'Est-ce que c'est?
Des choses telles que «la capitale de l'Écosse» sont appelées des termes définis et elles n'ont pas donné de mal de tête aux logiciens et aux philosophes pendant longtemps. Russell et Quine les ont classés en disant qu'ils ne sont pas réellement "référentiels", c'est-à-dire que c'est une erreur de penser que les exemples ci-dessus sont utilisés pour faire référence à des entités. La bonne façon de comprendre "Édimbourg est la capitale de l'Écosse depuis 1999", c'est-à-dire
Cette phrase ne peut pas être transformée en une phrase folle. Problème résolu! Le but de Quine était de dire que le langage naturel est désordonné, ou du moins compliqué, parce qu'il est conçu pour être pratique à utiliser, mais les philosophes et les logiciens devraient apporter de la clarté en les comprenant correctement. La transparence référentielle est un outil à utiliser pour apporter une telle clarté de sens .
Qu'est-ce que tout cela a à voir avec la programmation? Pas vraiment, en fait. Comme nous l'avons dit, la transparence référentielle est un outil à utiliser pour comprendre le langage, c'est-à-dire pour attribuer un sens . Christopher Strachey , qui a fondé le domaine de la sémantique des langages de programmation, l'a utilisé dans son étude du sens. Son document de base " Concepts fondamentaux dans les langages de programmation " est disponible sur le Web. C'est un beau papier et tout le monde peut le lire et le comprendre. Alors, faites-le. Vous serez très éclairé. Il introduit le terme "transparence référentielle" dans ce paragraphe:
L'utilisation de "en substance" suggère que Strachey le paraphrase afin de l'expliquer en termes simples. Les programmeurs fonctionnels semblent comprendre ce paragraphe à leur manière. Il y a 9 autres occurrences de "transparence référentielle" dans le document, mais elles ne semblent pas se soucier des autres. En fait, tout l'article de Strachey est consacré à expliquer la signification des langages de programmation impératifs . Mais, aujourd'hui, les programmeurs fonctionnels affirment que les langages de programmation impératifs ne sont pas référentiellement transparents. Strachey se retournerait dans sa tombe.
Nous pouvons sauver la situation. Nous avons dit que le langage naturel est "désordonné, ou du moins compliqué" car il est conçu pour être pratique à utiliser. Les langages de programmation sont de la même manière. Ils sont "désordonnés, ou au moins compliqués" car ils sont conçus pour être pratiques pour une utilisation pratique. Cela ne signifie pas qu'ils doivent nous confondre. Il suffit de les comprendre de la bonne façon, en utilisant un méta-langage qui est référentiellement transparent pour que nous ayons une clarté de sens. Dans l'article que j'ai cité, Strachey fait exactement cela. Il explique la signification des langages de programmation impératifs en les décomposant en concepts élémentaires, sans jamais perdre de clarté nulle part. Une partie importante de son analyse est de souligner que les expressions dans les langages de programmation ont deux types de "valeurs",valeurs r . Avant l'article de Strachey, cela n'était pas compris et la confusion régnait en maître. Aujourd'hui, la définition de C le mentionne régulièrement et chaque programmeur C comprend la distinction. (Il est difficile de dire si les programmeurs dans d'autres langues le comprennent aussi bien.)
Quine et Strachey étaient tous deux concernés par la signification des constructions de langage qui impliquent une certaine forme de dépendance au contexte. Par exemple, notre exemple "Édimbourg est la capitale de l'Écosse depuis 1999" signifie que la "capitale de l'Écosse" dépend du moment où elle est considérée. Cette dépendance au contexte est une réalité, à la fois dans les langages naturels et les langages de programmation. Même dans la programmation fonctionnelle, les variables libres et liées doivent être interprétées en fonction du contexte dans lequel elles apparaissent. La dépendance du contexte de tout type bloque la transparence référentielle d'une manière ou d'une autre. Si vous essayez de comprendre le sens des termes sans tenir compte des contextes dont ils dépendent, vous vous retrouverez à nouveau dans la confusion. Quine était préoccupé par le sens de la logique modale. Il a soutenu quela logique modale était référentiellement opaque et devrait être nettoyée en la traduisant en un cadre référentiel transparent (par exemple, en considérant la nécessité comme la prouvabilité). Il a largement perdu ce débat. Les logiciens et les philosophes ont trouvé que la sémantique mondiale possible de Kripke était parfaitement adéquate. Une situation similaire règne également avec une programmation impérative. La dépendance à l'État expliquée par Strachey et la dépendance au magasin expliquée par Reynolds (d'une manière similaire à la sémantique mondiale possible de Kripke) sont parfaitement adéquates. Les programmeurs fonctionnels ne connaissent pas grand-chose à cette recherche. Leurs idées sur la transparence référentielle doivent être prises avec un gros grain de sel.
[Note supplémentaire: Les exemples ci-dessus illustrent qu'une expression simple telle que «capitale de l'Écosse» a plusieurs niveaux de signification. À un certain niveau, nous pourrions parler de la capitale à l'heure actuelle. À un autre niveau, nous pourrions parler de toutes les capitales possibles que l'Écosse aurait pu avoir au fil du temps. Nous pouvons «zoomer» sur un contexte particulier et «dézoomer» pour couvrir tous les contextes assez facilement dans la pratique normale. L'efficacité du langage naturel utilise notre capacité à le faire. Les langages de programmation impératifs sont très efficaces de la même manière. Nous pouvons utiliser une variable x sur le côté droit d'une affectation (la valeur r ) pour parler de sa valeur dans un état particulier. Ou, nous pourrions parler de sa valeur lqui couvre tous les États. Les gens sont rarement confondus par de telles choses. Cependant, ils peuvent ou non être capables d'expliquer précisément toutes les couches de sens inhérentes aux constructions langagières. Toutes ces couches de sens ne sont pas nécessairement «évidentes» et il est de la science de les étudier correctement. Cependant, l'inarticulation des gens ordinaires pour expliquer de telles significations en couches n'implique pas qu'ils soient confus à leur sujet.]
Un "post-scriptum" ci-dessous relie cette discussion aux préoccupations de programmation fonctionnelle et impérative .
la source
La transparence référentielle, un terme couramment utilisé dans la programmation fonctionnelle, signifie que, étant donné une fonction et une valeur d'entrée, vous recevrez toujours la même sortie. C'est-à-dire qu'aucun état externe n'est utilisé dans la fonction.
Voici un exemple de fonction transparente référentielle:
Avec une fonction transparente référentielle, étant donné une entrée et une fonction, vous pouvez la remplacer par une valeur au lieu d'appeler la fonction. Ainsi, au lieu d'appeler plusOne avec un paramètre de 5, nous pourrions simplement le remplacer par 6.
Un autre bon exemple est celui des mathématiques en général. En mathématiques, étant donné une fonction et une valeur d'entrée, il correspondra toujours à la même valeur de sortie. f (x) = x + 1. Les fonctions mathématiques sont donc référentiellement transparentes.
Ce concept est important pour les chercheurs car il signifie que lorsque vous avez une fonction référentiellement transparente, elle se prête à une parallélisation et une mise en cache automatiques faciles.
La transparence référentielle est toujours utilisée dans les langages fonctionnels comme Haskell.
-
En revanche, il y a le concept d'opacité référentielle. Cela signifie le contraire. L'appel de la fonction peut ne pas toujours produire la même sortie.
Un autre exemple est une fonction membre dans un langage de programmation orienté objet. Les fonctions membres opèrent généralement sur ses variables membres et seraient donc opaques référentielles. Les fonctions des membres peuvent bien sûr être référentiellement transparentes.
Un autre exemple encore est une fonction qui lit à partir d'un fichier texte et imprime la sortie. Ce fichier texte externe pourrait changer à tout moment de sorte que la fonction serait référentiellement opaque.
la source
Une fonction référentiellement transparente est une fonction qui ne dépend que de son entrée.
la source
[Ceci est un post-scriptum de ma réponse du 25 mars, dans un effort pour rapprocher la discussion des préoccupations de programmation fonctionnelle / impérative.]
L'idée des programmeurs fonctionnels de la transparence référentielle semble différer de la notion standard de trois manières:
Alors que les philosophes / logiciens utilisent des termes comme "référence", "dénotation", "designatum" et " bedeutung " (terme allemand de Frege), les programmeurs fonctionnels utilisent le terme "valeur". (Ce n'est pas entièrement de leur fait. Je remarque que Landin, Strachey et leurs descendants ont également utilisé le terme "valeur" pour parler de référence / dénotation. Il peut s'agir simplement d'une simplification terminologique que Landin et Strachey ont introduite, mais il semble grande différence lorsqu'il est utilisé de manière naïve.)
Les programmeurs fonctionnels semblent croire que ces "valeurs" existent à l'intérieur du langage de programmation, pas à l'extérieur. Ce faisant, ils diffèrent à la fois des philosophes et des sémantistes du langage de programmation.
Ils semblent croire que ces "valeurs" sont censées être obtenues par évaluation.
Par exemple, l'article de Wikipedia sur la transparence référentielle dit ce matin:
Ceci est complètement en contradiction avec ce que disent les philosophes / logiciens. Ils disent qu'un contexte est référentiel ou référentiellement transparent si une expression dans ce contexte peut être remplacée par une autre expression qui fait référence à la même chose (une expression coréférentielle ). Qui sont ces philosophes / logiciens? Ils comprennent Frege , Russell , Whitehead , Carnap , Quine , Churchet d'innombrables autres. Chacun d'eux est une figure imposante. La puissance intellectuelle combinée de ces logiciens est pour le moins bouleversante. Tous sont unanimes dans la position selon laquelle les référents / dénotations existent en dehors du langage formel et les expressions dans le langage ne peuvent que parler d' eux. Ainsi, tout ce que l'on peut faire dans le langage est de remplacer une expression par une autre expression qui fait référence à la même entité. Les référents / dénotations eux - mêmes n'existent pas dans la langue. Pourquoi les programmeurs fonctionnels s'écartent-ils de cette tradition bien établie?
On pourrait supposer que les sémantistes du langage de programmation peuvent les avoir induits en erreur. Mais ils ne l'ont pas fait.
Landin :
Stoy :
Oiseau et échassier :
Ainsi, rétrospectivement, les efforts de Landin et Strachey pour simplifier la terminologie en remplaçant «référence» / «dénotation» par «valeur» auraient pu être peu judicieux. Dès que l'on entend parler d'une "valeur", on est tenté de penser à un processus d'évaluation qui y conduit. Il est également tentant de considérer ce que l'évaluation produit comme la "valeur", même s'il peut être tout à fait clair que ce n'est pas la dénotation. C'est ce que je pense être arrivé au concept de «transparence référentielle» aux yeux des programmeurs fonctionnels. Mais la "valeur" dont parlaient les premiers sémantistes n'est pas le résultat d'une évaluation ou la sortie d'une fonction ou quelque chose de ce genre. C'est la dénotation du terme.
Une fois que nous comprenons la soi-disant "valeur" d'une expression ("référence" ou "dénotation" dans le discours des philosophes classiques) comme un objet mathématique / conceptuel complexe, toutes sortes de possibilités s'ouvrent.
La réticence des programmeurs fonctionnels à appeler de tels langages "référentiellement transparents" implique simplement qu'ils sont réticents à admettre des objets mathématiques / conceptuels complexes comme des "valeurs". D'un autre côté, ils semblent parfaitement disposés à appeler un transformateur d'état une "valeur" lorsqu'il est placé dans leur propre syntaxe préférée et habillé avec un mot à la mode comme "monade". Je dois dire qu'ils sont totalement incohérents, même si nous leur accordons que leur idée de «transparence référentielle» a une certaine cohérence.
Un peu d'histoire pourrait éclairer la façon dont ces confusions ont vu le jour. La période entre 1962 et 1967 a été très intense pour Christopher Strachey. Entre 1962 et 1965, il a pris un emploi à temps partiel en tant qu'assistant de recherche chez Maurice Wilkes pour concevoir et mettre en œuvre le langage de programmation qui allait devenir le CPL. Il s'agissait d'un langage de programmation impératif, mais devait également disposer de puissantes capacités de langage de programmation fonctionnel. Landin, qui était un employé de Strachey dans sa société de conseil, a eu une énorme influence sur la vision de Strachey des langages de programmation. Dans le document de référence de 1965 " Les 700 prochains langages de programmation ", Landin promeut sans vergogne les langages de programmation fonctionnels (les appelant dénotatifslangages) et décrit les langages de programmation impératifs comme leur "antithèse". Dans la discussion qui a suivi, nous constatons que Strachey soulève des doutes sur la position forte de Landin.
En 1965, Strachey a pris la position d'un lecteur à Oxford et semble avoir travaillé essentiellement à plein temps sur le développement d'une théorie des impératifs et des sauts. En 1967, il était prêt avec une théorie, qu'il a enseignée dans son cours sur " Les concepts fondamentaux dans les langages de programmation " dans une école d'été de Copenhague. Les notes de cours étaient censées avoir été publiées, mais "malheureusement, en raison d'une révision dilatoire, les procédures ne se sont jamais concrétisées; cependant, comme une grande partie du travail de Strachey à Oxford, le journal a eu une circulation privée influente". ( Martin Campbell-Kelly )
La difficulté d'obtenir les écrits de Strachey aurait pu conduire à la propagation des confusions, les gens s'appuyant sur des sources secondaires et du ouï-dire. Mais, maintenant que les « concepts fondamentaux » sont facilement disponibles sur le Web, il n'est plus nécessaire de recourir à des devinettes. Nous devons le lire et nous faire une idée de ce que Strachey voulait dire. En particulier:
Toute discussion sur la "transparence référentielle" sans comprendre la distinction entre les valeurs L, les valeurs R et d'autres objets complexes qui peuplent l'univers conceptuel du programmeur impératif est fondamentalement erronée.
la source
Une expression est référentiellement transparente si elle peut être remplacée par sa valeur, sans changer l'algorithme, produisant un algorithme qui a les mêmes effets et qui sort sur la même entrée.
la source
Une fonction référentiellement transparente est une fonction qui agit comme une fonction mathématique; étant donné les mêmes entrées, il produira toujours les mêmes sorties. Cela implique que l'état transmis n'est pas modifié et que la fonction n'a pas d'état propre.
la source
Pour ceux qui ont besoin d'une explication concise, j'en risquerai une (mais lisez la divulgation ci-dessous).
La transparence référentielle dans un langage de programmation favorise le raisonnement équationnel - plus vous avez de transparence référentielle, plus il est facile de faire un raisonnement équationnel. Par exemple avec une (pseudo) définition de fonction,
fx = x + x,
la facilité avec laquelle vous pouvez (en toute sécurité) remplacer f (foo) par foo + foo dans le cadre de cette définition, sans avoir trop de contraintes sur l'endroit où vous pouvez effectuer cette réduction, est une bonne indication de la transparence référentielle de votre langage de programmation a.
Par exemple, si foo était x ++ au sens de la programmation C, vous ne pourriez pas effectuer cette réduction en toute sécurité (c'est-à-dire que si vous effectuez cette réduction, vous ne vous retrouveriez pas avec le même programme que celui avec lequel vous avez commencé).
Dans les langages de programmation pratiques, vous ne verrez pas une transparence référentielle parfaite, mais les programmeurs fonctionnels s'en soucient plus que la plupart (cf. Haskell, où c'est un objectif central).
(Divulgation complète: je suis un programmeur fonctionnel, donc par la réponse la plus élevée, vous devriez prendre cette explication avec un grain de sel.)
la source
Si vous êtes intéressé par l'étymologie (c.-à-d. Pourquoi ce concept a-t-il ce nom particulier), jetez un œil à mon article de blog sur le sujet. La terminologie vient du philosophe / logicien Quine.
la source
Dans 1, il y a une clarté de deux langues en question:
En 2, grâce à la proximité de l'objet et des métalangages, ils peuvent être confondus.
En tant qu'implémenteur de langage, je trouve que je dois constamment me souvenir de cette distinction.
Alors, le professeur Reddy, je peux vous paraphraser ainsi :-)
la source
J'espère que la réponse suivante complète et qualifie les 1ère et 3e réponses controversées.
Admettons qu'une expression désigne ou fasse référence à un référent. Cependant, la question est de savoir si ces référents peuvent être codés de manière isomorphe dans le cadre des expressions elles-mêmes, appelant ces expressions des «valeurs». Par exemple, les valeurs de nombres littéraux sont un sous-ensemble de l'ensemble d'expressions arithmétiques, les valeurs de vérité sont un sous-ensemble de l'ensemble d'expressions booléennes, etc. L'idée est d'évaluer une expression à sa valeur (si elle en a une). Ainsi, le mot «valeur» peut faire référence à une dénotation ou à un élément distinctif de l'ensemble d'expressions. Mais s'il y a un isomorphisme (une bijection) entre le référent et la valeur on peut dire que c'est la même chose. (Cela dit, il faut faire attention à définir les référents et l'isomorphisme, comme le prouve le domaine de la sémantique dénotationnelle. Pour mettre un exemple mentionné par les réponses à la 3ème réponse,
data Nat = Zero | Suc Nat
ne correspond pas comme prévu à l'ensemble des nombres naturels.)Écrivons
E[·]
pour une expression avec un trou, également connu dans certains milieux comme un «contexte». Deux exemples de contexte pour les expressions de type C sont[·]+1
et[·]++
.Écrivons
[[·]]
pour la fonction qui prend une expression (sans trou) et délivre sa signification (référent, dénotation, etc.) dans un univers fournissant du sens. (J'emprunte la notation au domaine de la sémantique dénotationnelle.)Adaptons quelque peu la définition de Quine de la manière suivante: un contexte
E[·]
est référentiellement transparent si deux expressionsE1
etE2
(pas de trous là-bas) telles que[[E1]] = [[E2]]
(c'est-à-dire les expressions dénotent / se réfèrent au même référent) alors c'est le cas qui[[E[E1]]] = [[E[E2]]]
(ie remplissant -dans le trou avec soitE1
ouE2
donne des expressions qui désignent également le même référent).La règle de Leibniz de substituer des égaux aux égaux est généralement exprimée comme «si
E1 = E2
alorsE[E1] = E[E2]
», ce qui dit queE[·]
c'est une fonction. Une fonction (ou d'ailleurs un programme calculant la fonction) est un mappage d'une source à une cible de sorte qu'il y ait au plus un élément cible pour chaque élément source. Les fonctions non déterministes sont misnomères, ils sont des relations, les fonctions ensembles livrent, etc. Si dans la règle de Leibniz l'égalité=
est dénotation alors les doubles crochets sont simplement pris pour acquis et élision. Un contexte référentiellement transparent est donc une fonction. Et la règle de Leibniz est l'ingrédient principal du raisonnement équationnel, de sorte que le raisonnement équationnel est définitivement lié à la transparence référentielle.Bien que ce
[[·]]
soit une fonction des expressions aux dénotations, cela pourrait être une fonction des expressions aux «valeurs» comprises comme un sous-ensemble restreint d'expressions, et[[·]]
peut être comprise comme une évaluation.Maintenant, si
E1
est une expression etE2
est une valeur, nous avons ce que je pense que la plupart des gens entendent par la définition de la transparence référentielle en termes d'expressions, de valeurs et d'évaluation. Mais comme l'illustrent les 1ère et 3ème réponses de cette page, il s'agit d'une définition inexacte.Le problème avec des contextes tels que
[·]++
n'est pas l'effet secondaire, mais que sa valeur n'est pas définie en C de manière isomorphe à sa signification. Les fonctions ne sont pas des valeurs (enfin, les pointeurs vers les fonctions le sont), contrairement aux langages de programmation fonctionnels. Landin, Strachey et les pionniers de la sémantique dénotationnelle ont été assez intelligents dans l'utilisation des mondes fonctionnels pour donner du sens.Pour les langages impératifs de type C, nous pouvons (grossièrement) fournir la sémantique aux expressions utilisant la fonction
[[·]] : Expression -> (State -> State x Value)
.Value
est un sous-ensemble deExpression
.State
contient des paires (identifiant, valeur). La fonction sémantique prend une expression et délivre comme sens une fonction de l'état actuel à la paire avec l'état mis à jour et une valeur. Par exemple,[[x]]
est la fonction de l'état actuel à la paire dont le premier composant est l'état actuel et dont le deuxième composant est la valeur de x. En revanche,[[x++]]
est la fonction de l'état actuel à la paire dont le premier composant est un état dans lequel la valeur de x est incrémentée, et dont le deuxième composant est cette même valeur. En ce sens, le contexte[·]++
est référentiellement transparent s'il satisfait à la définition donnée ci-dessus.Je pense que les programmeurs fonctionnels ont le droit d'utiliser la transparence référentielle dans le sens où ils récupèrent naturellement
[[·]]
en fonction des expressions aux valeurs. Les fonctions sont des valeurs de première classe et l'état peut également être une valeur, pas une dénotation. La monade d'état est (en partie) un mécanisme propre pour passer (ou enfiler) l'état.la source
Notez que ce concept de «sens» est quelque chose qui se passe dans l'esprit de l'observateur. Ainsi, la même "référence" peut signifier différentes choses pour différentes personnes. Ainsi, par exemple, nous avons une page de désambiguïsation à Édimbourg sur Wikipedia.
Un problème connexe qui peut apparaître dans le contexte de la programmation pourrait être le polymorphisme.
Et peut-être devrions-nous avoir un nom pour le cas spécial du polymorphisme (ou peut-être même de la coulée) où, pour nos besoins, les différents cas polymorphes sont sémantiquement équivalents (par opposition à être simplement similaires. Par exemple, le nombre 1 - qui pourrait être représenté en utilisant un type entier, ou un type complexe ou n'importe lequel d'une variété d'autres types - peut être traité de manière polymorphe).
la source
J'ai trouvé utile la définition de la transparence référentielle dans le livre " Structure and Implementation of Computer Programs " (le Wizard Book) car elle est complétée par une explication de la façon dont la transparence référentielle est violée en introduisant l' opération d'affectation . Découvrez le jeu de diapositives suivant que j'ai réalisé sur le sujet: https://www.slideshare.net/pjschwarz/introducing-assignment-invalidates-the-substitution-model-of-evaluation-and-violates-referential-transparency-as- expliqué dans sicp-the-wizard-book
la source
La transparence référentielle peut être simplement énoncée comme:
Par exemple, le langage de programmation Haskell est un langage fonctionnel pur; ce qui signifie qu'il est référentiellement transparent.
la source