Beachten Sie, ob dies für Sie geeignet ist, aber in funktionalen Sprachen wie Standard ML ist standardmäßig alles unveränderlich. Die Mutation wird durch einen generischen refErence-Typ unterstützt. Eine intVariable ist also unveränderlich, und eine ref intVariable ist ein veränderlicher Container für ints. Grundsätzlich sind Variablen echte Variablen im mathematischen Sinne (ein unbekannter, aber fester Wert) und refs sind "Variablen" im imperativen Programmiersinn - eine Speicherzelle, in die geschrieben und aus der gelesen werden kann. (Ich nenne sie gerne zuweisbare Werte .)
Ich denke, das Problem constist zweifach. Erstens fehlt C ++ die Garbage Collection, die für nicht triviale persistente Datenstrukturen erforderlich ist . const muss tief sein, um einen Sinn zu ergeben, aber es ist unpraktisch, vollständig unveränderliche Werte in C ++ zu haben.
Zweitens müssen Sie sich in C ++ anmelden const anstatt sich dagegen zu entscheiden. Wenn Sie jedoch constetwas vergessen und später korrigieren, werden Sie in die in der Antwort von @ RobY erwähnte "const poisoning" -Situation geraten, in der die constÄnderung im gesamten Code kaskadiert. Wenn dies constder Standard wäre, würden Sie sich nicht constrückwirkend bewerben . Außerdem führt das Hinzufügen von constüberall zu viel Rauschen im Code.
Ich vermute, dass die folgenden Mainstream-Sprachen (z. B. Java) stark vom Erfolg und der Denkweise von C und C ++ geprägt waren. Beispiel: Selbst bei der Garbage Collection gehen die meisten Collection-APIs von veränderlichen Datenstrukturen aus. Die Tatsache, dass alles veränderlich und unveränderlich ist, wird als Eckpfeiler angesehen und spricht Bände über die zwingende Denkweise hinter populären Sprachen.
EDIT : Nachdem ich über den Kommentar von greenoldman nachgedacht hatte, wurde mir klar, dass constes nicht direkt um die Unveränderlichkeit von Daten geht. constCodiert in den Typ der Methode, ob sie Nebenwirkungen auf die Instanz hat.
Mutationen können verwendet werden, um ein referenziell transparentes Verhalten zu erzielen . Angenommen, Sie haben eine Funktion, die beim sukzessiven Aufruf unterschiedliche Werte zurückgibt - zum Beispiel eine Funktion, aus der ein einzelnes Zeichen gelesen wird stdin. Wir könnten die Ergebnisse dieser Funktion zwischenspeichern / auswendig lernen, um einen referenziell transparenten Strom von Werten zu erzeugen. Der Stream ist eine verknüpfte Liste, deren Knoten die Funktion aufrufen, wenn Sie zum ersten Mal versuchen, ihren Wert abzurufen, dann aber das Ergebnis zwischenspeichern. Also wennstdin constains ist Hello, world!, wird beim ersten Versuch, den Wert des ersten Knotens abzurufen, einer gelesen charund zurückgegeben H. Danach kehrt es Hohne weitere Aufrufe weiter zum Lesen ein char. Ebenso würde der zweite Knoten einen Fest charausstdinWenn Sie zum ersten Mal versuchen, seinen Wert abzurufen, wird dieses eErgebnis zurückgegeben und zwischengespeichert.
Das Interessante dabei ist, dass Sie einen Prozess, der von Natur aus zustandsbehaftet ist, in ein Objekt verwandelt haben, das scheinbar zustandslos ist. Es war jedoch notwendig, den internen Zustand des Objekts zu mutieren (indem die Ergebnisse zwischengespeichert wurden), um dies zu erreichen - die Mutation war ein harmloser Effekt . Es ist unmöglich, unseren zu CharStream consterzeugen, obwohl sich der Stream wie ein unveränderlicher Wert verhält . Stellen Sie sich vor, es gibt eine StreamSchnittstelle mit constMethoden und alle Funktionen, die Sie erwarten const Streams. Sie CharStreamkönnen die Schnittstelle nicht implementieren!
( EDIT 2: Anscheinend gibt es ein C ++ - Schlüsselwort mutable, mit dem wir betrügen und machen könnenCharStream const . Jedoch zerstört diese Lücke die constGarantien - jetzt können Sie wirklich nicht sicher sein, dass etwas durch seine constMethoden nicht mutiert . Ich nehme an, dass es nicht so ist schlecht, da Sie die Lücke explizit beantragen müssen, aber immer noch voll und ganz auf das Ehrensystem angewiesen sind.)
Angenommen, Sie haben Funktionen höherer Ordnung, dh Sie können Funktionen als Argumente an andere Funktionen übergeben. constness ist Teil der Signatur einer Funktion, sodass Sie keineconst als Argumente an Funktionen übergeben, die constFunktionen erwarten . Eine blinde Durchsetzung constwürde zu einem Verlust der Allgemeinheit führen.
Schließlich manipulieren a const garantiert das Objekts nicht, dass es keinen externen (statischen oder globalen) Zustand hinter Ihrem Rücken mutiert, sodass constdie Garantien nicht so stark sind, wie sie anfänglich angezeigt werden.
Mir ist nicht klar, dass es allgemein gut ist, das Vorhandensein oder Nichtvorhandensein von Nebenwirkungen in das Typsystem zu kodieren.