Ich kann nicht genau erfassen, was Namensgleichheit ist. Ich bin mir aber ziemlich sicher, dass ich strukturelle Probleme habe. Ein Beispiel, das mein Professor gab, war dies:
%Vor%a und b sind beide strukturell und gleichbedeutend, während f und g nur strukturell gleichwertig sind. Ich verstehe nicht, warum a und b gleichbedeutend wären, aber f und g nicht.
Geben Sie Gleichheit ein
Die Bedeutung von grundlegenden Operationen wie Zuweisung (gekennzeichnet durch = in C) wird in einer Sprachdefinition angegeben. So zum Beispiel die Bedeutung von Aussagen wie
%Vor% Hier wird der Wert des Objekts y
in die Speicherplätze für die Variable x
kopiert.
Bevor jedoch eine Operation wie eine Zuweisung vom Übersetzer akzeptiert werden kann, müssen die Typen der beiden Operanden normalerweise identisch sein (oder vielleicht in einer anderen spezifizierten Weise kompatibel sein).
So muss ein Sprachübersetzer entscheiden, ob zwei Typen in einigen Fällen gleich sind. Wir betrachten nun, was es bedeutet zu sagen, dass zwei Arten "gleich" (oder gleichwertig) sind.
Es gibt zwei Standardmethoden, um zu bestimmen, ob zwei Typen gleich sind: Namensäquivalenz und strukturelle Äquivalenz .
Name Äquivalenz ist die einfachste: zwei Typen sind gleich, wenn und nur wenn sie den gleichen Namen haben. So zum Beispiel im Code (mit C-Syntax)
%Vor% Wenn Namensäquivalenz in der Sprache verwendet wird, dann wären x
und y
vom selben Typ und r
und s
wären vom selben Typ, aber vom Typ von x
oder y
wäre nicht gleich dem Typ von r
oder s
. Dies bedeutet, dass Aussagen wie
wäre gültig, aber Aussagen wie
%Vor%wäre nicht gültig (würde also von einem Übersetzer nicht akzeptiert).
Mit strukturelle Äquivalenz: , sind zwei Typen gleich und nur dann, wenn sie die gleiche "Struktur" haben, was auf verschiedene Arten interpretiert werden kann >
Eine strenge Interpretation wäre, dass die Namen und Typen jeder Komponente der beiden Typen identisch sein müssen und in der Typdefinition in derselben Reihenfolge aufgeführt sein müssen.
Eine weniger strenge Anforderung wäre, dass die Komponententypen in beiden Typen gleich und in der gleichen Reihenfolge sein müssen, aber die Namen der Komponenten könnten unterschiedlich sein.
Wenn wir uns wieder das obige Beispiel ansehen, würden wir mit strukturelle Äquivalenz die beiden Typen Stack
und Set
als äquivalent betrachten, was bedeutet, dass ein Übersetzer Anweisungen wie
(Beachten Sie, dass C
keine strukturelle Äquivalenz unterstützt und einen Fehler für die obige Zuweisung ergibt.)
Betrachten Sie die zwei folgenden Definitionen.
%Vor%Im obigen Beispiel werden die Variablen x und y unter der Namensäquivalenz als unterschiedliche Typen betrachtet: x verwendet den in Zeile 1 deklarierten Typ; y verwendet den in Zeile 4 deklarierten Typ. Die Namensäquivalenz basiert auf der Annahme, dass, wenn der Programmierer versucht, zwei Typdefinitionen zu schreiben, diese Definitionen wahrscheinlich verschiedene Typen darstellen sollen. (Ich bin nicht sicher über das Beispiel, das Sie gegeben haben)
Referenz: Programmiersprachen Pragmatik, von M.L. Scott
Der Begriff der Namensäquivalenz ist am sinnvollsten, wenn Sie die internen Datenstrukturen betrachten, die ein Compiler zur Darstellung von Typen verwenden könnte. Angenommen, die Typen werden als Zeiger auf Datenstrukturen dargestellt. Außerdem nehme ich an, dass ich die Typäquivalenzprüfung als einen einfachen Zeigervergleich (z. B. Namensäquivalenz) implementiere. Primitive Typen wie integer
und float
würden in einer globalen Umgebung gespeichert, da es nur eine begrenzte Anzahl von ihnen gibt. Außerdem, wenn ich integer
mit integer
vergleiche, sind sie garantiert äquivalent, da sie aufgrund dieser globalen Umgebung auf dieselbe Struktur verweisen.
Da ref
jedoch kein Typkonstruktor ist, kein atomarer Typ, kann ich unendlich viele Typen erzeugen (z. B. ref float
, ref ref float
usw.). Daher können wir sie nicht alle in einer globalen Umgebung speichern. Eine einfache Strategie, die der Compiler für die Verwaltung dieser Typen übernehmen kann, ist die Zuweisung einer neuen Struktur, wenn wir auf einen Typenkonstruktor stoßen. Wir ordnen ihm eine neue Datenstruktur zu. Die Instanz von ref float
würde also zu einer neuen Datenstruktur führen und die andere Instanz von ref float
würde zu einer völlig neuen, anderen Datenstruktur führen. Der Zeigervergleich schlägt fehl, und daher sind sie nicht gleichbedeutend.
Es gibt noch ein weiteres Puzzlestück, was die Semantik Ihres Zuweisungsoperators ist. Dieser Typ-Alias ist eine einfache Zeigerkopie im Compiler. Wenn ich also A=B
schreibe, ist A
immer der Name, der äquivalent zu B
ist. Aber, um es noch einmal zu wiederholen: F A
entspricht nicht dem Namen einer anderen Instanz von F A
!
a und b sind deshalb so, dass sie gleichbedeutend sind. f und g sind nicht so, sie sind nicht gleichbedeutend.
In einer Namenstyp-Äquivalenz haben zwei Variablen den gleichen Typ, wenn sie in derselben Deklaration oder in Deklarationen definiert sind, die denselben Typnamen verwenden. Daher sind die Variablen 'f'
und 'g'
in Ihrem Beispiel Äquivalente. Die Variablen 'a'
und 'b'
sind jedoch keine Äquivalente, da sie unterschiedliche Typnamen haben.
Unter der Äquivalenz des Strukturtyps haben zwei Variablen denselben Typ, wenn sie identische Strukturen haben. Die Variablen 'a'
und 'b'
sind also Äquivalente und auch die Variablen 'f'
und 'g'
sind Äquivalente, da Typen mit gleichem Namen natürlich die gleiche Struktur haben.
Referenz: Sebesta, Konzepte der Programmiersprachen, 10. Ausgabe.
Tags und Links type-equivalence