Getters et Setters dans les langages fonctionnels


9

L'un des principes de la programmation fonctionnelle est l'utilisation de fonctions pures. Une fonction Pure est une fonction sans effets secondaires et transparente par référence.

Les Getters ne sont pas référentiellement transparents - si un Setter est appelé entre des appels au Getter, la valeur de retour du Getter change même si ses paramètres ne l'ont pas (généralement pas de paramètres)

Les setters produisent des effets secondaires - L'appel d'un Setter manipule généralement une valeur qui n'est pas sa valeur de retour (en fait, traditionnellement, un setter ne renvoie rien)

Je sais qu'à Scala, nous acceptons simplement le fait que nous entremêlons deux paradigmes (fonctionnels et orientés objet) et utilisons des getters / setters comme nous le ferions dans un langage comme Java.

Dans un langage comme Haskell (avec lequel je ne parle pas couramment, mais on me dit que c'est plus vrai pour un langage fonctionnel "pur"), je suis juste curieux de savoir comment vous modéliseriez des propriétés sur des objets tels que les Getters sont référentiellement transparents et les Setters les effets secondaires sont-ils libres?

La solution consisterait-elle à renvoyer une copie de l'objet sur lequel le setter a été invoqué comme valeur de retour du setter, et cette copie contient la modification de la valeur de la propriété?


8
Les getters et setters ont l'objet comme paramètre - même s'il est généralement implicite - les getters sont donc référentiellement transparents.

@delnan, uniquement si l'attribut qu'il lit est immuable.
dan_waterworth

3
@dan_waterworth: Seulement si nous lisons le "même" dans "référentiellement transparent" comme identité d'objet. Si le fait que l'attribut sous-jacent soit différent en fait un appel avec des arguments différents (ce qui est conforme à la plupart des définitions de l'égalité). Ceci ignore un autre thread appelant un setter et le termine entre l'appel au getter et la fin du getter, mais dans ce cas, vous avez quand même des problèmes plus graves.

Réponses:


7

Exactement. Voir la méthode des classes de cas copyou le concept général des lentilles.

En particulier, si l'état doit changer, vous utiliserez une monade d'État. Des changements à cette monade d'état peuvent être effectués à travers des lentilles, ce qui facilite l'extraction d'informations de "l'état" et leur changement facile.

Voir aussi cette question sur le problème général qui vient d'une structure profonde comme «état» et y apporter des modifications. Les réponses ont de bons liens sur les lentilles et les fermetures à glissière si vous voulez approfondir cela.


Question Daniel: y a-t-il une raison particulière pour laquelle copy () est lié aux classes Case? Cela ne semble pas spécifique aux besoins (mauvais mot, mais je ne peux pas penser à un autre) des classes Case en particulier, il me semble (plus) plus d'une fonctionnalité adaptée à toutes les classes. Que faire si j'ai besoin de copy () sur ma classe non-case? Y a-t-il un trait que je peux utiliser pour obtenir cette fonctionnalité?
ThaDon

1
Les classes de cas @ThaDon sont censées être définies par leurs paramètres de constructeur - leur égalité, leur code de hachage et leur extracteur sont basés sur cette hypothèse, tout comme la méthode de copie. Sur les classes non-cas, n'importe qui peut deviner si les paramètres du constructeur sont tout ce qui est nécessaire pour copier une classe. Vous pouvez cependant écrire facilement votre propre méthode de copie.
Daniel C.Sobral

11

Eh bien, dans Haskell, les objets sont (généralement) immuables, donc les getters (que vous obtenez lorsque vous utilisez la syntaxe d'enregistrement) ou les fonctions qui agissent comme des getters sont référentiellement transparents. Et puis, vous ne "définissez" pas de valeurs sur les objets - au contraire, vous créez un nouvel objet similaire à l'ancien, mais avec une valeur différente pour l'un des champs. C'est aussi une fonction pure.


1
"les objets sont (généralement) immuables" quand ne le sont-ils pas?
sara

-1

"Les getters et setters ont l'objet comme paramètre - même s'il est généralement implicite - les getters sont donc référentiellement transparents. - delnan"

La transparence référentielle signifie que la fonction renvoie TOUJOURS la même sortie pour les mêmes entrées; donc si un attribut d'objet a été modifié par un setter, vous ne retournez pas la même sortie. :)


Mais, si l'objet a été modifié par un setter, l'entrée du getter (c'est-à-dire l'argument self implicite) a changé.
Stephen C. Steel

1
La valeur / pointeur de référence d'objet n'a pas changé, sauf si l'objet a été déplacé sur le tas.
Casey Hawthorne

5
Oui, mais logiquement, l'entrée implicite est l'objet lui-même, pas la valeur du pointeur.
Stephen C. Steel

"si un attribut d'objet a été modifié par un setter, vous ne retournez pas la même sortie": En termes fonctionnels, vous avez détruit le premier objet et en avez créé un nouveau. Pour des raisons de performances (évitez de copier et de mettre à jour les références de l'ancien vers le nouvel objet), vous stockez le nouvel objet dans la même zone de mémoire qui contenait l'ancien objet.
Giorgio
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.