Геттери та сетери на функціональних мовах


9

Одним із принципів функціонального програмування є використання чистих функцій. Чиста функція - це функція, яка не має побічних ефектів і є відносно прозорою.

Getters не є прозоро прозорими - якщо Setter викликається між дзвінками до Getter, повернене значення Getter змінюється, навіть якщо його параметри не мають (як правило, відсутні параметри)

Встановлювачі створюють побічні ефекти - виклик сеттера зазвичай маніпулює значенням, яке не є його зворотним значенням (насправді, традиційно сеттер нічого не повертає)

Я знаю, що в Scala ми просто сприймаємо той факт, що ми з'єднуємо дві парадигми (функціональну та об'єктно-орієнтовану) і використовуємо getters / setters так, як ми б на такій мові, як Java.

Такою мовою, як Haskell (якою я не вільно володію, але мені кажуть, є вірною "чистої" функціональної мови) Мені просто цікаво, як би ви моделювали властивості для таких об'єктів, що Getters є прозоро прозорими та Setters чи немає побічних ефектів?

Чи було б рішенням повернути копію об'єкта, на який встановлено встановлення, як повернуте значення програми, і ця копія містить зміну значення властивості?


8
Геттери і сеттери мають об'єкт як параметр - навіть незважаючи на те, що він зазвичай неявний - таким чином, геттери є прозоро прозорими.

@delnan, лише якщо атрибут, який він читає, є незмінним.
dan_waterworth

3
@dan_waterworth: Тільки якщо ми прочитаємо "те ж" у "референтно прозорому", як ідентичність об'єкта. Якщо факт, що лежить в основі атрибута, є різним, це викликає різні аргументи (що відповідає більшості визначень рівності). Це ігнорування ще однієї нитки, яка викликає сеттер і закінчує його між дзвінком до геттера та завершенням роботи, але в цьому випадку у вас все-таки виникають більш серйозні проблеми.

Відповіді:


7

Саме так. Дивіться метод класового випадку copyабо загальну концепцію лінз.

Зокрема, якщо державі потрібно змінити, ви використовуєте монаду держави. Зміни в монаді стану можуть бути внесені за допомогою лінз, що робить витяг інформації з "стану" та змінює її легко.

Дивіться також це питання про загальну проблему, яка випливає з глибокої структури на зразок "держави" та внесення змін до неї. Відповіді мають хороші посилання як на лінзи, так і на блискавки, якщо ви хочете заглибитись у це.


Питання Даніель: чи є якась конкретна причина того, що copy () прив’язаний до класів Case? Це не здається специфічним для потреб (неправильне слово, але не можу придумати інше) класів Case конкретно, мені здається (більше) функцією, придатною для всіх класів. Що робити, якщо мені потрібна копія () на моєму не-регістровому класі? Чи є якась ознака, яку я можу використовувати, щоб отримати цю функціональність?
ThaDon

1
Класи випадку @ThaDon повинні визначатися за їх конструкторськими параметрами - їх рівність, хеш-код та екстрактор засновані на цьому припущенні, як і метод копіювання. У класах, що не стосуються випадку, хтось здогадається, чи потрібні параметри конструктора для копіювання класу. Однак ви можете легко написати власний метод копіювання.
Даніель К. Собрал

11

Ну а в Haskell об'єкти (як правило) незмінні, тому getters (які ви отримуєте, коли використовуєте синтаксис запису) або функції, які діють як геттери, є відносно прозорими. І тоді ви не «встановлюєте» значення на об’єкти - якщо що-небудь створюєте новий об’єкт, подібний до старого, але з іншим значенням для одного з полів. Це теж чиста функція.


1
"об'єкти (як правило) незмінні", коли їх немає?
сара

-1

"Гетери та сетери мають об'єкт як параметр - навіть якщо він зазвичай неявний - тому геттери є референтно прозорими. - delnan"

Відносно прозорий означає, що функція ЗАВЖДИ повертає той же вихід на ті самі входи; тож якщо атрибут об’єкта змінено сетером, ви не повертаєте один і той же вихід. :)


Але, якщо об'єкт був змінений сеттером, вхід до getter (тобто неявний аргумент self) змінився.
Стівен К. Сталь

1
Опорне значення / покажчик об'єкта не змінилося, якщо об'єкт не переміщено на купі.
Кейсі Хоторн

5
Так, але логічно, що неявний вхід - це сам об'єкт, а не значення вказівника.
Стівен К. Сталь

"якщо атрибут об'єкта був змінений сетером, ви не повертаєте один і той же вихід": У функціональному відношенні ви знищили перший об'єкт і створили новий. З міркувань продуктивності (уникайте копіювання та оновлення посилань зі старого на новий об’єкт) ви зберігаєте новий об’єкт у тій самій області пам’яті, яка містила старий об’єкт.
Джорджіо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.