Чому для деяких функціональних мов потрібна транзакційна пам'ять програмного забезпечення?


24

Функціональні мови, за визначенням, не повинні підтримувати змінні стану. Чому тоді Haskell, Clojure та інші забезпечують реалізацію транзакційної пам'яті програмного забезпечення (STM)? Чи існує конфлікт між двома підходами?


Я просто хотів би зв’язати цей цікавий документ, який пояснює досить багато.
Сокіл

1
Щоб було зрозуміло, всі функціональні мови підтримують стан, але чистота наказує, що значення змінної не змінюється, як тільки вона встановлена.
Роберт Харві

Відповіді:


13

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

Основний момент полягає в тому, що функціональні мови перешкоджають зміненному стану, якщо вам це справді не потрібно . Загальний стиль полягає в програмуванні з використанням чистих функцій та незмінних даних, а взаємодія лише з "нечистим" змінним станом у конкретних частинах вашого коду, які цього вимагають. Таким чином, ви можете зберегти решту бази коду «чистою».

Я думаю, що є кілька причин, чому STM є більш поширеним у функціональних мовах:

  • Дослідження : STM - гаряча тема дослідження, і дослідники мови програмування часто вважають за краще працювати з функціональними мовами (тема самодослідження сама по собі, плюс простіше створити "докази" щодо поведінки програми)
  • Блокування не складається : STM можна розглядати як альтернативу блокувальним підходам до одночасності, який починає виникати в проблемах, коли ви масштабуєте складні системи шляхом складання різних компонентів. Це, мабуть, головна «прагматична» причина STM
  • STM добре поєднується з незмінністю : Якщо у вас велика незмінна структура, ви хочете переконатися, що вона залишається незмінною, тому вам не потрібно, щоб якась інша нитка надходила і мутувала якийсь під елемент. Так само, якщо ви можете гарантувати незмінність зазначеної структури даних, ви можете надійно трактувати це як стабільне "значення" у вашій системі STM.

Мені особисто подобається підхід Clojure до можливості зміни змін, але лише в умовах жорстко контрольованих "керованих посилань", які можуть брати участь у транзакціях STM. Все інше в мові "чисто функціональне".

  ;; define two accounts as managed references
  (def account-a (ref 100))
  (def account-b (ref 100))

  ;; define a transactional "transfer" function
  (defn transfer [ref-1 ref-2 amount]
    (dosync
      (if (>= @ref-1 amount)
        (do 
          (alter ref-1 - amount)
          (alter ref-2 + amount))
        (throw (Error. "Insufficient balance!")))))

  ;; make a stranfer
  (transfer account-a account-b 75)

  ;; inspect the accounts
  @account-a
  => 25

  @account-b
  => 175

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

Для додаткового просвітлення Річ Хікі чудово справляється з поясненням STM Clojure у цьому відео


3

Функціональні мови, за визначенням, не повинні підтримувати змінні стану

Ваше визначення неправильне. Мова, яка не може підтримувати стан, просто не може бути використана.

Різниця між функціональними та імперативними мовами полягає не в тому, що одна з них має державну, а інша - ні. Це певним чином вони підтримують державу.

Імперативні мови розповсюджуються державою по всій програмі.

Функціональні мови явно ізолюють та підтримують стан за допомогою підписів типів. І саме тому вони забезпечують складні механізми управління державою, такі як STM.


2

Іноді для програми потрібен стан, що змінюється (наприклад, вміст бази даних для веб-програми), і було б чудово використовувати її, не втрачаючи переваг функціонального програмування. У нефункціональних мовах стан, що змінюється, пронизує все. Якщо ви зробите це явним за допомогою якогось спеціального API , тоді ви можете обмежити його невеликим ідентифікованим регіоном, тоді як все інше залишається чисто функціональним. Переваги FP включають більш просту налагодження, повторне тестування одиниць, безболісну одночасність і дружність з багатоядерними / графічними процесорами.


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

Ти правий. Зрозуміло, що я не витрачаю достатньо часу на функціональне програмування, щоб пропустити це.
Буде Склад
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.