Bevor wir uns mit Identität befassen, definieren wir etwas genauer , was wir unter Gleichheit verstehen . Wir sagen, zwei Dinge sind genau dann gleich, wenn wir sie nicht unterscheiden können (siehe: Identität von Ununterscheidbaren ). Das heißt, ob zwei Dinge gleich sind oder nicht, hängt davon ab, wie wir sie untersuchen müssen.
Lassen Sie uns noch etwas mehr über die Programmierung nachdenken. Lassen wir unsere Vorurteile an der Tür und nehmen an, wir arbeiten in einer brandneuen unbekannten Sprache, in der alle Variablen und Werte unveränderlich sind. Nach der obigen Definition sind zwei Werte A
und B
genau dann gleich, wenn es KEINE Programme in der Sprache gibt, die unterschiedliche Ergebnisse liefern, wenn A
sie anstelle von B
oder umgekehrt verwendet werden. Lassen Sie uns sagen A
und B
sind (IEEE 754) schwimmt, und wenn in den Ausdruck _ + 1.0
, ist das Ergebnis 1.0
für beide A
und B
. Sicher A
und B
sind beide Null. Sind sie gleich? Das hängt davon ab, ob die Sprache eine Funktion bietet, mit der ich das Vorzeichen der Null bestimmen kann? Wenn nicht, sind sie gleich; Wenn ja, können sie nicht sein.
Daher sind zwei Werte jedes Mal gleich, wenn sie für alle möglichen Kombinationen von Operationen, die sie unterstützen, dieselben Ergebnisse liefern. Insbesondere unveränderliche Werte führen nicht zu unterschiedlichen Ergebnissen, je nachdem, welche Operationen zuvor auf sie angewendet wurden. Aus diesem Grund ist es uns egal, ob zwei Variablen auf zwei Kopien desselben Werts verweisen oder ob beide auf dieselbe Kopie verweisen.
Was hat das mit Veränderlichkeit zu tun? Veränderlichkeit impliziert, dass unsere Sprache eine Vorstellung von einer Speicherzelle hat, deren Inhalt überschrieben werden kann. Nehmen wir an, wir unterstützen unsere Sprache um veränderbare Speicherzellen:
ref <value>
erstellt eine neue Speicherzelle, die sich von allen anderen unterscheidet und auf initialisiert ist <value>
.
<variable> := <value>
überschreibt den Inhalt einer Referenzzelle.
!<variable>
Gibt den aktuell in einer Referenzzelle gespeicherten Wert zurück.
Lassen Sie uns nun darüber nachdenken, was Gleichheit für Speicherzellen bedeutet. Angenommen, A = ref 0
und B = A
. Betrachten Sie dieses Programm:
A := 1
print(!_)
Ersetzen Sie A
Drucke durch den Rohling 1
und ersetzen Sie auch B
Drucke 1
. Nehmen wir nun an A = ref 0
und B = ref 0
. In diesem Fall Einsetzen in die obigen Programm druckt 1
und 0
, da jetzt A
und B
zeigen Sie auf verschiedene Speicherzellen.
Es ist uns also wichtig, ob zwei Referenzen auf dieselbe Speicherzelle oder auf unterschiedliche Speicherzellen verweisen. Da dies wichtig ist, wäre es nützlich, zwei Referenzen effizient und allgemein voneinander zu unterscheiden. Unsere derzeitige Methode zum Vergleichen der Werte, die sie enthalten, und wenn sie gleich mutieren, ist einer von ihnen aus mehreren Gründen problematisch:
- Es hängt davon ab, ob die in den Speicherzellen gespeicherten Werte auf Gleichheit verglichen werden können. Gleichheit ist nicht für alle Typen sinnvoll - zum Beispiel ist sie für Funktionen im Allgemeinen bedeutungslos, da es keine allgemeine Methode gibt, um festzustellen, ob zwei unbekannte Funktionen gleich sind (dies wagt sich in das Gebiet des Halteproblems). Angesichts zweier Verweise auf Speicherzellen, in denen Funktionen gespeichert sind, können wir die Funktionen, die sie für die Gleichheit enthalten, nicht vergleichen.
- Es hängt davon ab, welchen Wert wir einer der beiden Referenzen zuweisen können. Selbst wenn Gleichheit für alle Typen in der Sprache sinnvoll ist, benötigen wir dennoch Zugriff auf einen Wert für jeden Typ, den wir vergleichen möchten. Was ist, wenn die Erstellung eines solchen Werts Nebenwirkungen hat?
- Der Referenzwert, den wir zum Mutieren einer der Referenzen verwenden, muss sich von dem Wert unterscheiden, den die Speicherzelle bereits hat, sodass wir tatsächlich zwei Werte benötigen.
- Der Code zum Vergleichen von Referenzen verschiedener Typen sieht bis auf die beiden von uns verwendeten Werte genau gleich aus.
- Wir müssen den Wert der Referenz, die wir mutieren, sichern und wiederherstellen, um zu vermeiden, dass sich die Bedeutung des Programms ändert.
Daher wäre es für die Sprache nützlich, eine Operation bereitzustellen, mit der direkt überprüft werden kann, ob zwei Referenzen auf dieselbe veränderbare Speicherzelle verweisen. Eine solche Funktion ist für unveränderliche Werte sinnlos; in der Tat würde ich sagen, es ist geradezu schädlich. Wenn es eine Möglichkeit 1
gab, festzustellen , ob zwei s an verschiedenen Stellen im Speicher gespeichert sind, kann es Programme geben, die sich darum kümmern, ob ich das eine 1
oder das andere übergebe. Ich möchte mir wirklich keine Sorgen machen, ob ich "das Richtige 1
" habe; Mathe ist schon schwer genug! Es ist also klar, dass die Überprüfung der Speichergleichheit hauptsächlich für veränderbare Typen nützlich ist.