Was ist referenzielle Transparenz?


285

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.


1
Wow, ich frage mich, warum der plötzliche Anstieg der Popularität dieser Frage ...
Claudiu

1
@claudia: Ich kann nicht sicher sagen, aber r / haskell hat Wind bekommen und viele hatten das Gefühl, dass Uday, obwohl ziemlich genau, ein bisschen Halse in der Community hat.
Efrey

6
@ Frey Ein Halse, vielleicht war es. Aber wenn funktionale Programmierer imperative Programmiersprachen und nebenwirksame funktionale Sprachen (wie Lisp und ML) abschießen und behaupten, sie seien nicht referenziell transparent, nehmen sie dann nicht einen Halse? Sollten sie nicht zumindest ihre Fakten richtig stellen, bevor sie dies tun?
Uday Reddy

2
@Claudiu Ich habe es auf dem Haskell Reddit gepostet und Conal hat es getwittert. Ich fand die Diskussion interessant und fand, dass sie eine breitere Diskussion verdient. Ich machte auf Udays Halse aufmerksam, um eine Diskussion anzuregen. Ich bin damit einverstanden, dass wir FPer manchmal selbstgefällig werden und ein gutes Produkt brauchen - gut gemacht an Uday, um es bereitzustellen!
Chrisdornan

7
@ Frey. Aus diesem Grund habe ich mich in meinem zweiten Beitrag für Bird und Wadler (Semantiker?) Zitiert. Die Fachleute wissen, dass das populäre Konzept der referenziellen Transparenz vage und möglicherweise inkohärent ist. Aber es wurde der Programmiergemeinschaft nie richtig erklärt. Hoffentlich wird mein Schreiben hier einen Unterschied machen.
Uday Reddy

Antworten:


362

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 .


10
Danke, aber ich bin nicht der Meinung, dass es einen "offensichtlichen" Erweiterungsbegriff von Gleichheit gibt. Als ich sagte, die "Hauptstadt Schottlands" beziehe sich auf die Stadt Edinburgh, haben Sie nicht zweimal darüber nachgedacht. Aber als ich anfing, über "seit 1999" zu sprechen, wurde Ihnen plötzlich bewusst, dass Zeit erforderlich ist. Der erweiterte Begriff der Gleichheit kann also sehr subtil sein und wird von Programmiersprachenforschern formalisiert. Menschen, die ein perfektes Verständnis der Extensionsgleichheit haben wollen, müssen die Früchte dieser Forschung lernen. Es kann überhaupt nicht "offensichtlich" sein.
Uday Reddy

5
Fantastisch! Eine willkommene Erleichterung für populäre Missverständnisse über RT, z. B. die Bindung an Funktionen . Oder definieren durch Ersetzen eines Ausdrucks durch seinen Wert (wie bei Wikipedia) - seltsamerweise, da Ausdrücke und Werte verschiedene Arten von Dingen sind. Vielleicht ist ein Ort, an dem Menschen falsch liegen, wenn sie die RT-Ness imperativer Sprachen betrachten, anzunehmen, dass diese "Werte" eher einfache Dinge wie Zahlen als komplexere Dinge wie Funktionen aus einem Geschäft sind.
Conal

13
@sclv Was den breiteren Einfluss der analytischen Philosophie auf die Informatik betrifft, sollte ich sagen, dass die Informatik, wie wir sie kennen, von Godel, Church, Kleene und Turing gegründet wurde. Diese Leute waren Logiker und sie waren sowohl mit den mathematischen als auch mit den philosophischen Aspekten der Logik vertraut, insbesondere mit den Traditionen von Peano, Frege, Russell, Whitehead, Carnap und Quine. Die frühen Pioniere der modernen Informatik kannten die Zusammenhänge. Aber das schnelle Wachstum der Informatik hat sie durchtrennt. Wir müssen zu ihnen zurückkehren.
Uday Reddy

5
@sclv Logik wird traditionell als Wissenschaft der Konsequenz ausgelegt . Aber ich denke, es ist eine breitere. Es ist die Wissenschaft der Information . Quine, ich sehe als den ersten, der die breitere Sichtweise hervorgebracht hat. "Wort und Objekt" ist eine Analyse des Informationsgehalts von Aussagen in natürlicher Sprache. Weder Philosophen noch Mathematiker haben sich jemals aktiv für Berechnungen interessiert , was angesichts der zentralen Rechenleistung für Zivilisation und Wissenschaft seit jeher ziemlich verwirrend ist. Wir müssen Wege finden, um sie zu interessieren.
Uday Reddy

3
@Conal: Ich habe eine neue Antwort hinzugefügt, die Ihren Standpunkt verstärkt. Es wird wahrscheinlich am Ende der Seite sein.
Uday Reddy

134

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.


1
Nur ein Kopf hoch, es ist möglich, ein vollständig referenziell transparentes Objekt mit referenziell transparenten Elementfunktionen zu haben. Siehe okmij.org/ftp/Scheme/oop-in-fp.txt
Jonathan Arkell

1
Und hier ist der Code, über den in diesem Artikel gesprochen wird: okmij.org/ftp/Scheme/pure-oo-system.scm
Jonathan Arkell

Im Fall einer vollständig referenziell transparenten Klasse wären wahrscheinlich alle Elementfunktionen statisch.
Brian R. Bondy

13
Worüber Sie hier sprechen, ist keine referenzielle Transparenz, obwohl sie allgemein als solche bezeichnet wird. Siehe Udays zwei Antworten und die Kommentare dazu. Insbesondere ist das, was Sie als "Ausgabe" bezeichnen, nicht die Bezeichnung. Wenn Sie "plusG 3" durch einen anderen Ausdruck mit demselben Wert / derselben Bezeichnung ersetzen würden, würden Sie tatsächlich ein Programm mit derselben Bedeutung erhalten, sodass RT in imperativen Sprachen gilt. Der Ausdruck "3 + 10" oder "13" hat nicht die gleiche Bedeutung wie "plusG 3", da die Bedeutung in imperativen Sprachen eine Funktion des "Speichers" (Zustand) ist.
Conal

1
Ich habe gerade einen Artikel über Nebenwirkungen und Zustandsänderungen gelesen und habe die Intuition, dass dies etwas mit RT zu tun hat. Könnten Sie bitte einen Hinweis hinzufügen?
Gaurav

91

Eine referenziell transparente Funktion hängt nur von ihrer Eingabe ab.


4
Aus diesem Grund ist es bei der OO-Programmierung schwierig, weil Objekte einen Status haben.
Kris

5
Ist es also richtig zu sagen, dass "referenziell transparent" mit "deterministisch" identisch ist, wenn Funktionen beschrieben werden? Wenn nicht, was ist der Unterschied zwischen den beiden Begriffen?
mwolfe02

1
Dies klingt auch nach einer Definition einer "reinen" Funktion.
Evgeny A.

75

[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. "

Vogel und Wadler :

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.

  • Strachey interpretierte Variablen in imperativen Programmiersprachen als L-Werte , wie in meiner Antwort vom 25. März erwähnt. Dies ist ein ausgeklügeltes konzeptionelles Objekt, das keine direkte Darstellung innerhalb der Syntax einer Programmiersprache hat.
  • Er interpretierte Befehle in solchen Sprachen auch als Zustandsfunktionen, eine weitere Instanz eines komplexen mathematischen Objekts, das kein "Wert" innerhalb der Syntax ist.
  • Sogar ein Nebeneffekt-Funktionsaufruf in C hat einen genau definierten "Wert" als Zustandstransformator, der Zustände auf Paare von Zuständen und Werten abbildet (die sogenannte "Monade" in der Terminologie funktionaler Programmierer).

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:

  • In Abschnitt 3.2 befasst er sich mit "Ausdrücken", in denen er über "referenzielle Transparenz mit R-Wert" spricht.
  • Sein Abschnitt 3.3 befasst sich mit "Befehlen", in denen er über "L-Wert-Referenztransparenz" spricht.
  • In Abschnitt 3.4.5 spricht er über "Funktionen und Routinen" und erklärt, dass "jede Abweichung der referenziellen Transparenz von R-Werten in einem R-Wert-Kontext entweder durch Zerlegen des Ausdrucks in mehrere Befehle und einfachere Ausdrücke beseitigt werden sollte, oder wenn das stellt sich als schwierig heraus, das Thema eines Kommentars. "

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.


10
Ich denke, es ist hervorzuheben, dass die Verwechslung dieser beiden Begriffe "Wert" (Bewertungen vs. Bezeichnungen) funktionale Programmierer in ihrer Kritik an imperativen Sprachen irreführt , bei denen die Kluft zwischen den Begriffen groß ist.
Conal

8
dh der Bewertungsbegriff führt zu der Schlussfolgerung, dass imperative Sprachen keine RT sind, während der Bezeichnungsbegriff dies nicht tut.
Conal

12
Es scheint mir, dass, sobald Sie die Denotationssemantik einer Sprache wirklich vollständig festgelegt haben, es nicht anders kann, als referenziell transparent zu sein. Dies scheint also gleichbedeutend damit zu sein, dass der Begriff in Bezug auf Programmiersprachen nicht nützlich ist.
Tom Crockett

20
Es scheint also, dass die Leute die Gewohnheit haben, einen Begriff zu verwenden, um etwas wesentlich anderes zu bedeuten als das, was andere Leute meinten, als sie diesen Begriff in der Vergangenheit verwendeten. Zu dem sage ich: Willkommen in der englischen Sprache.
Daniel Pratt

17
@DanielPratt: Wenn Nebenwirkungsfreiheit das ist, was funktionale Programmierer bedeuten wollen, warum nennen sie es dann "referentielle Transparenz"? Sie können es einfach "Nebenwirkungsfreiheit" nennen, was eine vollkommen klare Idee ist. Niemand muss beim Stapelaustausch fragen, was "Nebenwirkungsfreiheit" bedeutet. Wo ist die Notwendigkeit, grandiose klassische Begriffe zu entführen, die niemand zu verstehen scheint?
Uday Reddy

23

Ein Ausdruck ist referenziell transparent, wenn er durch seinen Wert ersetzt werden kann, ohne den Algorithmus zu ändern. Dies führt zu einem Algorithmus, der dieselben Effekte und Ausgaben bei derselben Eingabe hat.


18

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.


10

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.)


3
Ich habe kein Problem mit Sprachen, die das Gleichstellungsdenken erleichtern. Aber ich würde bestreiten, dass es irgendetwas mit "referentieller Transparenz" zu tun hat, wie es klassisch definiert ist. Zweitens denke ich als praktischer Programmierer, dass das Denken in Gleichstellungen überbewertet ist. Die in der Praxis wichtige Argumentation hat mit Vorbedingungen, Nachbedingungen, Invarianten und Datenabstraktion zu tun. Für Menschen, die sich auf solche Argumentationstechniken verlassen, scheinen Nebenwirkungen nicht viel zu bedeuten. Obwohl ich Ihnen zustimme, dass Nebenwirkungen in Ausdrücken eine schlechte Idee sind, scheinen sie kein Killerargument darzustellen.
Uday Reddy

1
@UdayReddy Nur weil funktionale Programmierer eine bestimmte Methode zum Einwählen der referenziellen Transparenz in ihren Programmen gewählt haben (Beseitigung von Nebenwirkungen und Entwicklung einer ausgeklügelten und leistungsfähigen Algebra von Programmen) oder einige Praktiker haben, die die referenzielle Transparenz wahrscheinlich nicht so gut verstehen wie Sie glauben, dass dies nicht bedeutet, dass funktionale Programmiersprachen die referenzielle Transparenz nicht erhöhen oder dass funktionale Sprachprogrammierer und Compiler-Autoren diese Erhöhung der formalen Traktierbarkeit nicht für viele gute Zwecke ausnutzen.
Chrisdornan

2
Chris: Uday wies darauf hin, dass Strachey das Problem der referentiellen Opazität in der Semantik von Programmiersprachen beseitigt hat, insbesondere für imperative Sprachen. Funktionale Programmierer können also nicht "die referenzielle Transparenz in ihren Programmen hochwählen". Als konkretes Beispiel ist Haskell IO keine Hilfe bei RT, gerade weil keine RT-Hilfe benötigt wird.
Conal

2
@chrisdornan: Entschuldigung für meinen ersten Kommentar oben. Ich selbst hatte Schwierigkeiten herauszufinden, was ich in den ersten beiden Sätzen zu sagen versuchte :-( Aber hier ist eine Erklärung. Betrachten Sie einen zweistufigen oder mehrstufigen Staging-Kalkül. Jeder Staging-Operator ist referenziell undurchsichtig. Es ist tatsächlich so Sie können jedoch in jeder Phase vollkommenes Gleichungsdenken betreiben. Daher hat jeder referenziell undurchsichtige Operator Grenzen für das Gleichungsdenken festgelegt. Sie haben jedoch immer noch Gleichungsdenken innerhalb dieser Grenzen.
Uday Reddy

1
@chrisdomain: Darüber hinaus möchten nur sehr wenige Menschen referenzielle Transparenz-Puristen sein, um solche Inszenierungsbetreiber zu verbannen. Diese Operatoren sind äußerst nützlich. Das Programmieren ohne sie durch manuelles Staging wäre mühsam, fehleranfällig und hässlich. Und wenn Sie manuell inszenieren, erhalten Sie keine gleichberechtigten Argumente mehr als zuvor. Das Verbot guter Programmiergeräte im puristischen Streben nach gleichem Denken wäre also so, als würde man sich die Nase abschneiden, um sich das Gesicht zu ärgern.
Uday Reddy

8

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.


4
  1. Die Denotationssemantik basiert auf der Modellierung von Sprachen, indem Domänen erstellt werden, die denotierbare Werte darstellen .
  2. Funktionale Programmierer verwenden den Begriff Wert , um die Konvergenz einer Berechnung zu beschreiben, die auf den Umschreiberegeln der Sprache basiert, d. H. seine operative Semantik.

In 1 gibt es eine Klarheit von zwei fraglichen Sprachen:

  • derjenige, der modelliert wird, die Objektsprache
  • die Sprache der Modellierung, die Metasprache

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.


1
Ha ha. Danke für die Erklärung. Das Problem ist auch, dass funktionale Programmierer so tun, als hätten sie einen allgemeinen Begriff von "referentieller Transparenz", der für alle Programmiersprachen gilt . Dies hängt jedoch von ihrem Begriff "Wert" ab, der für andere Sprachen möglicherweise sinnvoll ist oder nicht. Um eine allgemeine Theorie der "referentiellen Transparenz" zu behaupten, müssen sie eine allgemeine Theorie "Wert" erzeugen. Das fehlt bisher.
Uday Reddy

4

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 [·]+1und [·]++.

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 E1und 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 E1oder E2führt zu Ausdrücken, die auch denselben Referenten bezeichnen).

Leibniz 'Regel, Gleiches durch Gleiches zu ersetzen, wird typischerweise als "wenn E1 = E2dann 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 E1es sich nun um einen Ausdruck und E2einen 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).

Valueist eine Teilmenge von Expression. Stateenthä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.


Vermutlich sind die "1." und "3." Antworten UdayReddys "25. März" - bzw. "Postscript" -Antworten. Ordnungszahlen sind kein guter Weg, um auf Antworten in SO zu verweisen. Stimmen und Akzeptanzen können sich nicht nur im Laufe der Zeit ändern, sondern es gibt auch mehrere auswählbare Ordnungen.
Philipxy

2

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).


0

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


0

Referenzielle Transparenz kann einfach wie folgt angegeben werden:

  • Ein Ausdruck, der in jedem Kontext immer das gleiche Ergebnis liefert [1] ,
  • Wenn eine Funktion zweimal dieselben Parameter erhält, muss sie zweimal dasselbe Ergebnis liefern [2] .

Zum Beispiel ist die Programmiersprache Haskell eine reine Funktionssprache; was bedeutet, dass es referenziell transparent ist.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.