Was bedeutet der Begriff referentielle Transparenz ? Ich habe gehört, dass es als "es bedeutet, dass Sie Gleiches durch Gleiches ersetzen können" beschrieben wurde, aber dies scheint eine unzureichende Erklärung zu sein.
Was bedeutet der Begriff referentielle Transparenz ? Ich habe gehört, dass es als "es bedeutet, dass Sie Gleiches durch Gleiches ersetzen können" beschrieben wurde, aber dies scheint eine unzureichende Erklärung zu sein.
Antworten:
Der Begriff "referentielle Transparenz" stammt aus der analytischen Philosophie , dem Zweig der Philosophie, der Konstrukte, Aussagen und Argumente natürlicher Sprache auf der Grundlage der Methoden der Logik und Mathematik analysiert. Mit anderen Worten, es ist das Fach außerhalb der Informatik, das der sogenannten Semantik der Programmiersprache am nächsten kommt . Der Philosoph Willard Quine war für die Initiierung des Konzepts der referentiellen Transparenz verantwortlich, war aber auch in den Ansätzen von Bertrand Russell und Alfred Whitehead enthalten.
"Referenztransparenz" ist im Kern eine sehr einfache und klare Idee. Der Begriff "Referent" wird in der analytischen Philosophie verwendet, um über das zu sprechen, worauf sich ein Ausdruck bezieht . Es ist ungefähr das Gleiche wie das, was wir unter "Bedeutung" oder "Bezeichnung" in der Semantik der Programmiersprache verstehen. Am Beispiel von Andrew Birkett ( Blogbeitrag ) bezieht sich der Begriff "die Hauptstadt Schottlands" auf die Stadt Edinburgh. Das ist ein einfaches Beispiel für einen "Referenten".
Ein Kontext in einem Satz ist "referenziell transparent", wenn das Ersetzen eines Begriffs in diesem Kontext durch einen anderen Begriff, der sich auf dieselbe Entität bezieht, die Bedeutung nicht ändert. Beispielsweise
Das schottische Parlament tritt in der Hauptstadt Schottlands zusammen.
bedeutet das gleiche wie
Das schottische Parlament tritt in Edinburgh zusammen.
Der Kontext "Das schottische Parlament trifft sich in ..." ist also ein referenziell transparenter Kontext. Wir können "die Hauptstadt Schottlands" durch "Edinburgh" ersetzen, ohne die Bedeutung zu ändern. Anders ausgedrückt, der Kontext kümmert sich nur darum, worauf sich der Begriff bezieht, und sonst nichts. In diesem Sinne ist der Kontext "referenziell transparent".
Auf der anderen Seite, im Satz,
Edinburgh ist seit 1999 die Hauptstadt Schottlands.
Wir können einen solchen Ersatz nicht machen. Wenn wir das tun würden, würden wir "Edinburgh ist seit 1999 Edinburgh" bekommen, was eine verrückte Sache ist und nicht die gleiche Bedeutung wie der ursprüngliche Satz vermittelt. Es scheint also, dass der Kontext "Edinburgh ist ... seit 1999" referenziell undurchsichtig ist (das Gegenteil von referenziell transparent). Es geht anscheinend um etwas mehr als das, worauf sich der Begriff bezieht. Was ist es?
Dinge wie "die Hauptstadt Schottlands" werden als bestimmte Begriffe bezeichnet, und sie haben Logikern und Philosophen lange Zeit keine mageren Kopfschmerzen bereitet. Russell und Quine haben sie aussortiert und gesagt, dass sie nicht wirklich "referentiell" sind, dh es ist ein Fehler zu glauben, dass die obigen Beispiele verwendet werden, um sich auf Entitäten zu beziehen. Der richtige Weg zu verstehen, "Edinburgh ist seit 1999 die Hauptstadt Schottlands" ist zu sagen
Schottland hat seit 1999 eine Hauptstadt und diese Hauptstadt ist Edinburgh.
Dieser Satz kann nicht in einen verrückten umgewandelt werden. Problem gelöst! Der Sinn von Quine war zu sagen, dass natürliche Sprache chaotisch oder zumindest kompliziert ist, weil sie für den praktischen Gebrauch praktisch ist, aber Philosophen und Logiker sollten Klarheit schaffen, indem sie sie richtig verstehen. Referentielle Transparenz ist ein Werkzeug, um eine solche Klarheit der Bedeutung zu erreichen .
Was hat das alles mit Programmierung zu tun? Eigentlich nicht sehr viel. Wie bereits erwähnt, ist referenzielle Transparenz ein Werkzeug, um die Sprache zu verstehen, dh um Bedeutung zuzuweisen . Christopher Strachey , der das Gebiet der Semantik der Programmiersprache begründete, verwendete es in seinem Studium der Bedeutung. Sein Grundpapier " Grundlegende Konzepte in Programmiersprachen " ist im Internet verfügbar. Es ist ein wunderschönes Papier und jeder kann es lesen und verstehen. Also bitte. Du wirst sehr erleuchtet sein. Er führt den Begriff "referentielle Transparenz" in diesen Absatz ein:
Eine der nützlichsten Eigenschaften von Ausdrücken ist die von Quine referentielle Transparenz. Im Wesentlichen bedeutet dies, dass, wenn wir den Wert eines Ausdrucks finden möchten, der einen Unterausdruck enthält, das einzige, was wir über den Unterausdruck wissen müssen, sein Wert ist. Alle anderen Merkmale des Unterausdrucks, wie seine interne Struktur, die Anzahl und Art seiner Komponenten, die Reihenfolge, in der sie bewertet werden, oder die Farbe der Tinte, in der sie geschrieben sind, sind für den Wert des Hauptausdrucks irrelevant Ausdruck.
Die Verwendung von "im Wesentlichen" legt nahe, dass Strachey es paraphrasiert, um es in einfachen Worten zu erklären. Funktionale Programmierer scheinen diesen Absatz auf ihre eigene Weise zu verstehen. Es gibt 9 andere Vorkommen von "referentieller Transparenz" in dem Papier, aber sie scheinen sich nicht um die anderen zu kümmern. Tatsächlich widmet sich das gesamte Papier von Strachey der Erklärung der Bedeutung zwingender Programmiersprachen . Heute behaupten funktionale Programmierer jedoch, dass zwingende Programmiersprachen nicht referenziell transparent sind. Strachey würde sich in seinem Grab umdrehen.
Wir können die Situation retten. Wir sagten, dass natürliche Sprache "chaotisch oder zumindest kompliziert" ist, weil sie für den praktischen Gebrauch praktisch ist. Programmiersprachen sind genauso. Sie sind "chaotisch oder zumindest kompliziert", weil sie für den praktischen Gebrauch praktisch sind. Das bedeutet nicht, dass sie uns verwirren müssen. Sie müssen nur richtig verstanden werden, indem eine Metasprache verwendet wird, die referenziell transparent ist, damit wir eine klare Bedeutung haben. In dem von mir zitierten Artikel macht Strachey genau das. Er erklärt die Bedeutung imperativer Programmiersprachen, indem er sie in elementare Konzepte zerlegt, ohne dabei an Klarheit zu verlieren. Ein wichtiger Teil seiner Analyse besteht darin, darauf hinzuweisen, dass Ausdrücke in Programmiersprachen zwei Arten von "Werten" haben.r-Werte . Vor Stracheys Papier wurde dies nicht verstanden und es herrschte Verwirrung. In der heutigen Definition von C wird dies routinemäßig erwähnt, und jeder C-Programmierer versteht die Unterscheidung. (Ob die Programmierer in anderen Sprachen es gleich gut verstehen, ist schwer zu sagen.)
Sowohl Quine als auch Strachey befassten sich mit der Bedeutung von Sprachkonstruktionen, die irgendeine Form von Kontextabhängigkeit beinhalten. Zum Beispiel bedeutet unser Beispiel "Edinburgh ist seit 1999 die Hauptstadt Schottlands", dass "Hauptstadt Schottlands" von dem Zeitpunkt abhängt, zu dem es in Betracht gezogen wird. Eine solche Kontextabhängigkeit ist sowohl in natürlichen Sprachen als auch in Programmiersprachen Realität. Auch in der funktionalen Programmierung sind freie und gebundene Variablen in Bezug auf den Kontext zu interpretieren, in dem sie auftreten. Die Kontextabhängigkeit jeglicher Art blockiert auf die eine oder andere Weise die referenzielle Transparenz. Wenn Sie versuchen, die Bedeutung von Begriffen zu verstehen, ohne Rücksicht auf die Kontexte, von denen sie abhängen, würden Sie erneut Verwirrung stiften. Quine befasste sich mit der Bedeutung der Modallogik. Er hielt dasDie modale Logik war referenziell undurchsichtig und sollte bereinigt werden, indem sie in einen referenziell transparenten Rahmen übersetzt wird (z. B. indem die Notwendigkeit als Beweisbarkeit betrachtet wird). Er hat diese Debatte weitgehend verloren. Logiker und Philosophen fanden Kripkes mögliche Weltsemantik vollkommen ausreichend. Eine ähnliche Situation herrscht auch bei der imperativen Programmierung. Die von Strachey erklärte Zustandsabhängigkeit und die von Reynolds erklärte Speicherabhängigkeit (ähnlich wie Kripkes mögliche Weltsemantik) sind vollkommen ausreichend. Funktionale Programmierer wissen nicht viel über diese Forschung. Ihre Ideen zur referenziellen Transparenz sind mit einem großen Salzkorn aufzunehmen.
[Zusätzlicher Hinweis: Die obigen Beispiele veranschaulichen, dass ein einfacher Ausdruck wie "Hauptstadt Schottlands" mehrere Bedeutungsebenen hat. Auf einer Ebene könnten wir derzeit über die Hauptstadt sprechen. Auf einer anderen Ebene könnten wir über alle möglichen Hauptstädte sprechen, die Schottland im Laufe der Zeit gehabt haben könnte. Wir können in einen bestimmten Kontext "hineinzoomen" und "herauszoomen", um alle Kontexte in der normalen Praxis ganz einfach zu überspannen. Die Effizienz der natürlichen Sprache nutzt unsere Fähigkeit dazu. Imperative Programmiersprachen sind in ähnlicher Weise effizient. Wir können eine Variable x auf der rechten Seite einer Zuweisung (den r-Wert ) verwenden, um über ihren Wert in einem bestimmten Zustand zu sprechen. Oder wir könnten über seinen l-Wert sprechendas überspannt alle Staaten. Menschen sind selten durch solche Dinge verwirrt. Sie können jedoch möglicherweise alle Bedeutungsebenen, die Sprachkonstrukten innewohnen, genau erklären oder nicht. Alle diese Bedeutungsebenen sind nicht unbedingt „offensichtlich“ und es ist eine Frage der Wissenschaft, sie richtig zu studieren. Die Unartikulierbarkeit gewöhnlicher Menschen, solche vielschichtigen Bedeutungen zu erklären, bedeutet jedoch nicht, dass sie über sie verwirrt sind.]
Ein separates "Postscript" unten bezieht diese Diskussion auf die Belange der funktionalen und imperativen Programmierung .
Referentielle Transparenz, ein Begriff, der häufig in der funktionalen Programmierung verwendet wird, bedeutet, dass Sie bei einer Funktion und einem Eingabewert immer dieselbe Ausgabe erhalten. Das heißt, in der Funktion wird kein externer Zustand verwendet.
Hier ist ein Beispiel für eine referenzielle transparente Funktion:
int plusOne(int x)
{
return x+1;
}
Mit einer referenziellen transparenten Funktion können Sie bei einer Eingabe und einer Funktion diese durch einen Wert ersetzen, anstatt die Funktion aufzurufen. Anstatt plusOne mit einem Parameter von 5 aufzurufen, könnten wir dies einfach durch 6 ersetzen.
Ein weiteres gutes Beispiel ist die Mathematik im Allgemeinen. In der Mathematik wird eine Funktion und ein Eingabewert immer demselben Ausgabewert zugeordnet. f (x) = x + 1. Daher sind Funktionen in der Mathematik referenziell transparent.
Dieses Konzept ist für Forscher wichtig, da es sich bei einer referenziell transparenten Funktion für eine einfache automatische Parallelisierung und Zwischenspeicherung eignet.
Referenzielle Transparenz wird immer in funktionalen Sprachen wie Haskell verwendet.
- -
Im Gegensatz dazu gibt es das Konzept der referentiellen Undurchsichtigkeit. Dies bedeutet das Gegenteil. Das Aufrufen der Funktion führt möglicherweise nicht immer zur gleichen Ausgabe.
//global G
int G = 10;
int plusG(int x)
{//G can be modified externally returning different values.
return x + G;
}
Ein weiteres Beispiel ist eine Elementfunktion in einer objektorientierten Programmiersprache. Mitgliedsfunktionen arbeiten üblicherweise mit ihren Mitgliedsvariablen und wären daher referenziell undurchsichtig. Mitgliedsfunktionen können natürlich referenziell transparent sein.
Ein weiteres Beispiel ist eine Funktion, die aus einer Textdatei liest und die Ausgabe druckt. Diese externe Textdatei kann sich jederzeit ändern, sodass die Funktion referenziell undurchsichtig ist.
Eine referenziell transparente Funktion hängt nur von ihrer Eingabe ab.
[Dies ist ein Nachtrag zu meiner Antwort vom 25. März, um die Diskussion näher an die Belange der funktionalen / imperativen Programmierung heranzuführen.]
Die Vorstellung der funktionalen Programmierer von referentieller Transparenz scheint sich in drei Punkten vom Standardbegriff zu unterscheiden:
Während die Philosophen / Logiker Begriffe wie "Referenz", "Bezeichnung", "Designatum" und " Bedeutung " verwenden, verwenden funktionale Programmierer den Begriff "Wert". (Dies ist nicht ganz ihre Aufgabe. Ich stelle fest, dass Landin, Strachey und ihre Nachkommen den Begriff "Wert" auch verwendeten, um über Referenz / Bezeichnung zu sprechen. Es mag nur eine terminologische Vereinfachung sein, die Landin und Strachey eingeführt haben, aber es scheint eine zu sein großer Unterschied bei naiver Verwendung.)
Funktionale Programmierer scheinen zu glauben, dass diese "Werte" innerhalb der Programmiersprache existieren, nicht außerhalb. Dabei unterscheiden sie sich sowohl von den Philosophen als auch von den Programmiersprachen-Semantikern.
Sie scheinen zu glauben, dass diese "Werte" durch Bewertung erhalten werden sollen.
Zum Beispiel heißt es heute Morgen im Wikipedia-Artikel über referenzielle Transparenz :
Ein Ausdruck wird als referenziell transparent bezeichnet, wenn er durch seinen Wert ersetzt werden kann, ohne das Verhalten eines Programms zu ändern (mit anderen Worten, ein Programm zu erhalten, das dieselben Effekte und Ausgaben bei derselben Eingabe hat).
Dies steht völlig im Widerspruch zu dem, was die Philosophen / Logiker sagen. Sie sagen, dass ein Kontext referenziell oder referenziell transparent ist, wenn ein Ausdruck in diesem Kontext durch einen anderen Ausdruck ersetzt werden kann , der sich auf dasselbe bezieht (einen Koreferenzausdruck ). Wer sind diese Philosophen / Logiker? Dazu gehören Frege , Russell , Whitehead , Carnap , Quine , Churchund unzählige andere. Jeder von ihnen ist eine hoch aufragende Figur. Die kombinierte intellektuelle Kraft dieser Logiker ist gelinde gesagt weltbewegend. Alle sind sich einig in der Position, dass Referenten / Bezeichnungen außerhalb der formalen Sprache existieren und Ausdrücke innerhalb der Sprache nur über sie sprechen können. Alles, was man innerhalb der Sprache tun kann, ist, einen Ausdruck durch einen anderen Ausdruck zu ersetzen, der sich auf dieselbe Entität bezieht. Die Referenzen / Bezeichnungen selbst existieren nicht innerhalb der Sprache. Warum weichen die funktionalen Programmierer von dieser etablierten Tradition ab?
Man könnte annehmen, dass die Semantiker der Programmiersprache sie irregeführt haben könnten. Aber sie haben es nicht getan.
Landin :
(a) jeder Ausdruck hat eine verschachtelte Unterausdruckstruktur, (b) jeder Unterausdruck bezeichnet etwas (normalerweise eine Zahl, einen Wahrheitswert oder eine numerische Funktion) , (c) das, was ein Ausdruck bezeichnet, dh sein "Wert", hängt nur von der ab Werte seiner Unterausdrücke, nicht auf andere Eigenschaften von ihnen. [Hervorhebung hinzugefügt]
Stoy :
Das einzige, was für einen Ausdruck wichtig ist, ist sein Wert, und jeder Unterausdruck kann durch jeden anderen gleichwertigen ersetzt werden [Hervorhebung hinzugefügt]. Darüber hinaus ist der Wert eines Ausdrucks innerhalb bestimmter Grenzen immer gleich, wenn er auftritt. "
Der Wert eines Ausdrucks hängt nur von den Werten seiner konstituierenden Ausdrücke ab (falls vorhanden), und diese Unterausdrücke können frei durch andere ersetzt werden, die denselben Wert besitzen [Hervorhebung hinzugefügt].
Rückblickend könnten die Bemühungen von Landin und Strachey, die Terminologie durch Ersetzen von "Referenz" / "Bezeichnung" durch "Wert" zu vereinfachen, unklug gewesen sein. Sobald man von einem "Wert" hört, besteht die Versuchung, an einen Bewertungsprozess zu denken, der dazu führt. Es ist ebenso verlockend, sich das, was die Bewertung hervorbringt, als "Wert" vorzustellen, auch wenn klar sein mag, dass dies nicht die Bezeichnung ist. Ich habe festgestellt, dass dies mit dem Konzept der "referentiellen Transparenz" in den Augen funktionaler Programmierer geschehen ist. Aber der "Wert", von dem die frühen Semantiker sprachen, ist nicht das Ergebnis einer Bewertung oder der Ausgabe einer Funktion oder dergleichen. Es ist die Bezeichnung des Begriffs.
Sobald wir den sogenannten "Wert" eines Ausdrucks ("Referenz" oder "Bezeichnung" im Diskurs der klassischen Philosophen) als ein komplexes mathematisch-konzeptuelles Objekt verstehen, eröffnen sich alle Arten von Möglichkeiten.
Die Zurückhaltung funktionaler Programmierer, solche Sprachen als "referenziell transparent" zu bezeichnen, impliziert lediglich, dass sie solche komplexen mathematischen / konzeptuellen Objekte nur ungern als "Werte" zulassen. Andererseits scheinen sie durchaus bereit zu sein, einen Zustandstransformator als "Wert" zu bezeichnen, wenn er in ihre eigene Lieblingssyntax eingegeben und mit einem Modewort wie "Monade" versehen wird. Ich muss sagen, dass sie völlig inkonsistent sind, auch wenn wir ihnen gewähren, dass ihre Vorstellung von "referentieller Transparenz" eine gewisse Kohärenz aufweist.
Ein bisschen Geschichte könnte etwas Licht auf die Entstehung dieser Verwirrungen werfen. Die Zeit zwischen 1962 und 1967 war für Christopher Strachey sehr intensiv. Zwischen 1962 und 1965 nahm er eine Teilzeitstelle als wissenschaftlicher Mitarbeiter bei Maurice Wilkes an, um die Programmiersprache CPL zu entwerfen und zu implementieren. Dies war eine zwingende Programmiersprache, sollte aber auch über leistungsstarke funktionale Programmiersprachen verfügen. Landin, ein Mitarbeiter von Strachey in seiner Beratungsfirma, hatte einen großen Einfluss auf Stracheys Sicht auf Programmiersprachen. Im Grenzstein 1965 Papier „ Next 700 Programmiersprachen “, fördert ungeniert Landin funktionalen Programmiersprachen (nannte sie denotativenSprachen) und beschreibt imperative Programmiersprachen als ihre "Antithese". In der anschließenden Diskussion stellen wir fest, dass Strachey Zweifel an Landins starker Position aufkommen lässt.
... DLs bilden eine Teilmenge aller Sprachen. Sie sind eine interessante Untergruppe, die jedoch nur dann unpraktisch ist, wenn Sie daran gewöhnt sind. Wir brauchen sie, weil wir im Moment nicht wissen, wie man Beweise mit Sprachen konstruiert, die Imperative und Sprünge enthalten. [Hervorhebung hinzugefügt]
1965 übernahm Strachey die Position eines Lesers in Oxford und scheint im Wesentlichen Vollzeit an der Entwicklung einer Theorie der Imperative und Sprünge gearbeitet zu haben. Bis 1967 war er mit einer Theorie fertig, die er in seinem Kurs über " Grundlegende Konzepte in Programmiersprachen " an einer Kopenhagener Sommerschule unterrichtete. Die Vorlesungsunterlagen hätten veröffentlicht werden sollen, aber "leider kam das Verfahren aufgrund der dilatorischen Bearbeitung nie zustande; wie ein Großteil von Stracheys Arbeiten in Oxford hatte die Zeitung jedoch eine einflussreiche private Auflage." ( Martin Campbell-Kelly )
Die Schwierigkeit, Stracheys Schriften zu erhalten, hätte dazu führen können, dass die Verwirrungen verbreitet wurden und sich die Menschen auf Sekundärquellen und Hörensagen stützten. Jetzt, da " Grundlegende Konzepte " im Internet verfügbar sind, besteht keine Notwendigkeit mehr, auf Vermutungen zurückzugreifen. Wir sollten es lesen und uns selbst überlegen, was Strachey meinte. Bestimmtes:
Jede Rede von "referentieller Transparenz", ohne die Unterscheidung zwischen L-Werten, R-Werten und anderen komplexen Objekten zu verstehen, die das konzeptuelle Universum des imperativen Programmierers bevölkern, ist grundlegend falsch.
Eine referenziell transparente Funktion wirkt wie eine mathematische Funktion. Bei gleichen Eingaben werden immer die gleichen Ausgaben erzeugt. Dies bedeutet, dass der übergebene Status nicht geändert wird und dass die Funktion keinen eigenen Status hat.
Für diejenigen, die eine kurze Erklärung benötigen, werde ich eine riskieren (aber lesen Sie die Offenbarung unten).
Referenzielle Transparenz in einer Programmiersprache fördert das Denken in Gleichstellungen - je mehr referenzielle Transparenz Sie haben, desto einfacher ist es, Gleichungen zu argumentieren. ZB mit einer (Pseudo-) Funktionsdefinition,
fx = x + x,
Die Leichtigkeit, mit der Sie f (foo) im Rahmen dieser Definition (sicher) durch foo + foo ersetzen können, ohne zu viele Einschränkungen zu haben, wo Sie diese Reduzierung durchführen können, ist ein guter Hinweis darauf, wie viel referenzielle Transparenz Ihre Programmiersprache hat hat.
Wenn foo beispielsweise x ++ im Sinne der C-Programmierung wäre, könnten Sie diese Reduzierung nicht sicher durchführen (das heißt, wenn Sie diese Reduzierung durchführen würden, würden Sie nicht das gleiche Programm erhalten, mit dem Sie begonnen haben).
In praktischen Programmiersprachen sehen Sie keine perfekte referenzielle Transparenz, aber funktionale Programmierer kümmern sich mehr als die meisten anderen darum (vgl. Haskell, wo dies ein Kernziel ist).
(Vollständige Offenlegung: Ich bin ein funktionierender Programmierer. Nach der besten Antwort sollten Sie diese Erklärung mit einem Körnchen Salz nehmen.)
Wenn Sie sich für die Etymologie interessieren (dh warum hat dieses Konzept diesen bestimmten Namen), schauen Sie sich meinen Blog-Beitrag zum Thema an. Die Terminologie stammt vom Philosophen / Logiker Quine.
In 1 gibt es eine Klarheit von zwei fraglichen Sprachen:
In 2 können sie dank der Nähe des Objekts und der Metasprachen verwirrt werden.
Als Sprachimplementierer muss ich mich ständig an diese Unterscheidung erinnern.
Also, Prof. Reddy, darf ich Sie so umschreiben :-)
Im Kontext der funktionalen Programmierung und Semantik ist der Begriff referentielle Transparenz nicht referenziell transparent.
Die folgende Antwort, die ich hoffe, ergänzt und qualifiziert die umstrittenen 1. und 3. Antworten.
Lassen Sie uns gewähren, dass ein Ausdruck einen Referenten bezeichnet oder sich auf ihn bezieht. Eine Frage ist jedoch, ob diese Referenzen als Teil der Ausdrücke selbst isomorph codiert werden können, wobei solche Ausdrücke als "Werte" bezeichnet werden. Beispielsweise sind Literalzahlenwerte eine Teilmenge der Menge der arithmetischen Ausdrücke, Wahrheitswerte eine Teilmenge der Menge der Booleschen Ausdrücke usw. Die Idee besteht darin, einen Ausdruck auf seinen Wert zu bewerten (falls vorhanden). Das Wort 'Wert' kann sich also auf eine Bezeichnung oder auf ein unterschiedliches Element der Menge von Ausdrücken beziehen. Aber wenn es einen Isomorphismus (eine Bijektion) zwischen dem Referenten und dem Wert gibt, können wir sagen, dass sie dasselbe sind. (Dies bedeutet, dass man vorsichtig sein muss, um die Referenten und den Isomorphismus zu definieren, wie dies durch das Gebiet der Denotationssemantik bewiesen wird. Um ein Beispiel zu nennen, das durch Antworten auf die dritte Antwort erwähnt wird,data Nat = Zero | Suc Nat
entspricht nicht wie erwartet der Menge der natürlichen Zahlen.)
Schreiben wir E[·]
für einen Ausdruck mit einem Loch, der in einigen Bereichen auch als "Kontext" bezeichnet wird. Zwei Kontextbeispiele für C-ähnliche Ausdrücke sind [·]+1
und
[·]++
.
Schreiben wir [[·]]
für die Funktion, die einen Ausdruck (ohne Loch) nimmt und dessen Bedeutung (Referent, Bezeichnung usw.) in einem bedeutungsgebenden Universum liefert. (Ich leihe mir eine Notation aus dem Bereich der Denotationssemantik aus.)
Lassen Sie uns die Definition von Quine formal etwas wie folgt anpassen: Ein Kontext E[·]
ist referenziell transparent, wenn zwei Ausdrücke gegeben werden E1
und E2
(keine Löcher dort), so dass [[E1]] = [[E2]]
(dh die Ausdrücke bezeichnen / beziehen sich auf denselben Referenten), dann ist es der Fall, dass [[E[E1]]] = [[E[E2]]]
(dh füllen -in dem Loch mit entweder E1
oder E2
führt zu Ausdrücken, die auch denselben Referenten bezeichnen).
Leibniz 'Regel, Gleiches durch Gleiches zu ersetzen, wird typischerweise als "wenn E1 = E2
dann E[E1] = E[E2]
" ausgedrückt
, was besagt, dass dies E[·]
eine Funktion ist. Eine Funktion (oder im Übrigen ein Programm, das die Funktion berechnet) ist eine Zuordnung von einer Quelle zu einem Ziel, sodass für jedes Quellelement höchstens ein Zielelement vorhanden ist. Nicht deterministische Funktionen sind Fehlbezeichnungen, sie sind entweder Beziehungen, Funktionen, die Mengen liefern usw. Wenn in Leibniz 'Regel die Gleichheit =
denotational ist, werden die doppelten Klammern einfach als selbstverständlich angesehen und entfernt. Ein referenziell transparenter Kontext ist also eine Funktion. Und Leibniz 'Regel ist der Hauptbestandteil des Gleichungsdenkens, so dass Gleichstellungsdenken definitiv mit referentieller Transparenz zusammenhängt.
Obwohl [[·]]
es sich um eine Funktion von Ausdrücken zu Bezeichnungen handelt, kann es sich um eine Funktion von Ausdrücken zu 'Werten' handeln, die als eingeschränkte Teilmenge von Ausdrücken [[·]]
verstanden wird und als Bewertung verstanden werden kann.
Wenn E1
es sich nun um einen Ausdruck und E2
einen Wert handelt, haben wir das, was meiner Meinung nach von den meisten Menschen gemeint ist, wenn sie referenzielle Transparenz in Bezug auf Ausdrücke, Werte und Bewertung definieren. Wie die erste und dritte Antwort auf dieser Seite zeigen, ist dies eine ungenaue Definition.
Das Problem mit Kontexten wie [·]++
ist nicht der Nebeneffekt, sondern dass sein Wert in C nicht isomorph zu seiner Bedeutung definiert ist. Funktionen sind keine Werte (also Zeiger auf Funktionen), während dies in funktionalen Programmiersprachen der Fall ist. Landin, Strachey und die Pioniere der denotationalen Semantik waren ziemlich geschickt darin, funktionale Welten zu nutzen, um Bedeutung zu verleihen.
Für imperative C-ähnliche Sprachen können wir Ausdrücken mit der Funktion (grob) Semantik verleihen [[·]] : Expression -> (State -> State x Value)
.
Value
ist eine Teilmenge von Expression
. State
enthält Paare (Bezeichner, Wert). Die semantische Funktion nimmt einen Ausdruck und liefert als Bedeutung eine Funktion vom aktuellen Zustand an das Paar mit dem aktualisierten Zustand und einem Wert. Zum Beispiel [[x]]
ist die Funktion vom aktuellen Zustand zu dem Paar, dessen erste Komponente der aktuelle Zustand und dessen zweite Komponente der Wert von x ist. Im Gegensatz dazu [[x++]]
ist dies die Funktion vom aktuellen Zustand bis zum Paar, dessen erste Komponente ein Zustand ist, in dem der Wert von x inkrementiert wird, und dessen zweite Komponente genau dieser Wert ist. In diesem Sinne ist der Kontext [·]++
referenziell transparent, wenn er die oben angegebene Definition erfüllt.
Ich denke, funktionale Programmierer sind berechtigt, referenzielle Transparenz in dem Sinne zu verwenden, dass sie sich natürlich [[·]]
als Funktion von Ausdrücken zu Werten erholen . Funktionen sind erstklassige Werte und der Zustand kann auch ein Wert sein, keine Bezeichnung. Die Zustandsmonade ist (teilweise) ein sauberer Mechanismus zum Übergeben (oder Einfädeln) des Zustands.
Beachten Sie, dass dieses Konzept der "Bedeutung" im Kopf des Betrachters geschieht. Somit kann dieselbe "Referenz" für verschiedene Personen unterschiedliche Bedeutungen haben. So haben wir zum Beispiel eine Disambiguierungsseite für Edinburgh in Wikipedia.
Ein verwandtes Problem, das im Zusammenhang mit der Programmierung auftreten kann, könnte der Polymorphismus sein.
Und vielleicht sollten wir einen Namen für den Sonderfall des Polymorphismus (oder vielleicht sogar des Gießens) haben, bei dem für unsere Zwecke die unterschiedlichen polymorphen Fälle semantisch äquivalent sind (anstatt nur ähnlich zu sein. Zum Beispiel die Zahl 1 - die dargestellt werden könnte Verwendung eines ganzzahligen Typs oder eines komplexen Typs oder eines einer Vielzahl anderer Typen - kann polymorph behandelt werden).
Ich fand die Definition der referenziellen Transparenz im Buch " Struktur und Implementierung von Computerprogrammen " (das Assistentenbuch) nützlich, da sie durch eine Erklärung ergänzt wird, wie die referenzielle Transparenz durch die Einführung der Zuweisungsoperation verletzt wird . Schauen Sie sich das folgende Dia-Deck an, das ich zu diesem Thema erstellt habe: https://www.slideshare.net/pjschwarz/introducing-assignment-invalidates-the-substitution-model-of-evaluation-and-violates-referential-transparency-as- erklärte-in-sicp-the-Wizard-Buch
Referenzielle Transparenz kann einfach wie folgt angegeben werden:
Zum Beispiel ist die Programmiersprache Haskell eine reine Funktionssprache; was bedeutet, dass es referenziell transparent ist.