Getter und Setter in funktionalen Sprachen

9

Einer der Grundsätze der funktionalen Programmierung ist die Verwendung von reinen Funktionen. Eine Pure-Funktion ist nebenwirkungsfrei und referenziell transparent.

Getter sind nicht referentiell transparent - wenn ein Setter zwischen dem Aufruf der Getter, die Getter Rückgabewert ändert , auch wenn seine Parameter nicht ( in der Regel keine Parameter) aufgerufen wird

Setter verursachen Nebenwirkungen - Das Aufrufen eines Setters manipuliert normalerweise einen Wert, der nicht der Rückgabewert ist (tatsächlich gibt ein Setter traditionell nichts zurück).

Ich weiß, dass wir in Scala die Tatsache akzeptieren, dass wir zwei Paradigmen (funktional und objektorientiert) miteinander verbinden und Getter / Setter verwenden, wie wir es in einer Sprache wie Java tun würden.

In einer Sprache wie Haskell (die ich nicht fließend beherrsche, aber mir wurde gesagt, dass sie einer "reinen" Funktionssprache besser entspricht) bin ich nur neugierig, wie Sie Eigenschaften auf Objekten modellieren würden, bei denen Getters referenziell transparent und Setter sind sind Nebenwirkungen frei?

Wäre die Lösung, eine Kopie des Objekts, für das der Setter aufgerufen wurde, als Rückgabewert des Setters zurückzugeben, und diese Kopie enthält die Änderung des Eigenschaftswerts?

ThaDon
quelle
8
Getter und Setter haben das Objekt als Parameter - auch wenn es in der Regel implizit ist - so Getter ist referentiell transparent.
@delnan, nur wenn das Attribut, das es liest, unveränderlich ist.
dan_waterworth
3
@dan_waterworth: Nur wenn wir das "gleiche" in "referenziell transparent" als Objektidentität lesen. Wenn das zugrunde liegende Attribut unterschiedlich ist, wird es mit unterschiedlichen Argumenten aufgerufen (was mit den meisten Definitionen der Gleichheit übereinstimmt). Dies ignoriert einen anderen Thread, der einen Setter aufruft und ihn zwischen dem Aufruf des Getters und dem Beenden des Getters beendet, aber in diesem Fall haben Sie trotzdem ernstere Probleme.

Antworten:

7

Genau. Siehe Fallklassenmethode copyoder das allgemeine Konzept von Objektiven.

Insbesondere wenn der Status geändert werden muss, verwenden Sie eine Statusmonade. Änderungen an dieser Zustandsmonade können durch Linsen vorgenommen werden, was das Extrahieren von Informationen aus dem "Zustand" und das Ändern dieser Informationen erleichtert.

Siehe auch diese Frage zum allgemeinen Problem, das von einer tiefen Struktur wie "Zustand" herrührt und Änderungen daran vornimmt. Die Antworten haben gute Links sowohl zu Objektiven als auch zu Reißverschlüssen, wenn Sie näher darauf eingehen möchten.

Daniel C. Sobral
quelle
Frage Daniel: Gibt es einen bestimmten Grund, warum copy () an Fallklassen gebunden ist? Dies scheint nicht spezifisch für die Bedürfnisse (falsches Wort, aber ich kann mir kein anderes vorstellen) von Fallklassen zu sein, es scheint (für mich) eher eine Funktion zu sein, die für alle Klassen geeignet ist. Was ist, wenn ich copy () für meine Nicht-Fall-Klasse benötige? Gibt es eine Eigenschaft, mit der ich diese Funktionalität erhalten kann?
ThaDon
1
@ ThaDon-Fallklassen sollen durch ihre Konstruktorparameter definiert werden - ihre Gleichheit, ihr Hashcode und ihr Extraktor basieren auf dieser Annahme, ebenso wie die Kopiermethode. Bei Nicht-Fall-Klassen kann man nur raten, ob die Konstruktorparameter alles sind, was zum Kopieren einer Klasse benötigt wird. Sie können jedoch problemlos Ihre eigene Kopiermethode schreiben.
Daniel C. Sobral
11

Nun, in Haskell, Objekte sind ( in der Regel) unveränderlich, so Getter (die Sie erhalten , wenn Sie Datensatz Syntax verwenden) oder Funktionen , die wirken wie Getter sind referentiell transparent. Und dann "setzen" Sie keine Werte für Objekte - wenn überhaupt, erstellen Sie ein neues Objekt, das dem alten ähnlich ist, aber einen anderen Wert für eines der Felder hat. Dies ist auch eine reine Funktion.

MatrixFrog
quelle
1
"Objekte sind (normalerweise) unveränderlich" wann nicht?
Sara
-1

"Getter und Setter haben das Objekt als Parameter - obwohl es normalerweise implizit ist - so dass Getter referenziell transparent sind. - delnan"

Referenziell transparent bedeutet, dass die Funktion IMMER dieselbe Ausgabe für dieselben Eingaben zurückgibt. Wenn also ein Objektattribut von einem Setter geändert wurde, geben Sie nicht dieselbe Ausgabe zurück. :) :)

Casey Hawthorne
quelle
Wenn das Objekt jedoch von einem Setter geändert wurde, hat sich die Eingabe in den Getter (dh das implizite Selbstargument) geändert.
Stephen C. Steel
1
Der Objektreferenzwert / Zeiger hat sich nur geändert, wenn das Objekt auf dem Heap verschoben wurde.
Casey Hawthorne
5
Ja, aber logischerweise ist die implizite Eingabe das Objekt selbst, nicht der Wert des Zeigers.
Stephen C. Steel
"Wenn ein Objektattribut von einem Setter geändert wurde, geben Sie nicht dieselbe Ausgabe zurück": In funktionaler Hinsicht haben Sie das erste Objekt zerstört und ein neues erstellt. Aus Leistungsgründen (vermeiden Sie das Kopieren und Aktualisieren von Referenzen vom alten zum neuen Objekt) speichern Sie das neue Objekt in demselben Speicherbereich, in dem sich das alte Objekt befand.
Giorgio