Відмінності Clojure між Ref, Var, Agent, Atom, з прикладами


110

Я дуже новачок у Clojure. Чи можете ви, хлопці, дати мені пояснення щодо реальних сценаріїв. Я маю на увазі, де використовувати Ref, Var, Agent, Atom. Я читав книгу, але все ще не міг зрозуміти приклади реального світу.

Відповіді:


174

Я настійно рекомендую "Радість Клуджура" або "програмування Clojure" для реальної відповіді на це питання, я можу відтворити короткий фрагмент мотивації для кожного:

почніть з перегляду цього відео з поняття ідентичності та / або вивчення тут .

  • Рефлекси призначені для координованого синхронного доступу до "Багато ідентичностей".
  • Атоми призначені для некоординованого синхронного доступу до однієї ідентичності.
  • Агенти призначені для некоординованого асинхронного доступу до однієї ідентичності.
  • Vars призначені для локальних ізольованих ідентифікацій потоків із загальним значенням за замовчуванням.

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

Некоординований доступ використовується тоді, коли потрібно оновити лише одну особу, це дуже поширений випадок.

Синхронний доступ використовується тоді, коли очікується, що дзвінок зачекає, поки всі посвідчення не будуть встановлені перед продовженням.

Асинхронний доступ - це "вогонь і забудь" і нехай Ідентичність в свій час досягне свого нового стану.


Якщо я хочу лише змінитись, якщо я хочу лише змінити state-a, але посилаюся на state-bце, мені все-таки потрібна refправильна? Отже, це не зміна кількох речей, а посилання на кілька речей, змінюючи будь-яку з них?
event_jr

2
Так, ви, здається, правильно розумієте, що state-a і state-b повинні бути обома, якщо ви хочете, щоб нове значення в state-a базувалося на послідовному поєднанні значень в a і b. Потрібно, щоб це нове значення було обчислено в контексті, коли стан-а та стан-b, коли відповідає іншому. Якщо вони обидва відмови, якщо b змінюється на середині, тоді транзакція буде перезапущена і використовувати нові значення і a, і b. Подумайте про використання ensureфункції: clojure.github.io/clojure/clojure.core-api.html#clojure.core/…, щоб зробити це явним і більш ефективним.
Артур Ульфельтт

3
Може бути пояснення того, що Isolated із спільними засобами за замовчуванням можна додати для завершення відповіді?
Дідьє А.

1
"Координований доступ використовується тоді, коли два особи повинні бути змінені разом ...". Чи варто це "змінити"?
Carcigenicate

40

Посилання є для стану, який потрібно синхронізувати між потоками. Якщо вам потрібно відслідковувати купу різних речей, і вам іноді доведеться робити операції, які записують кілька речей одночасно, використовуйте реф. Кожен раз, коли у вас є кілька різних станів, використання refs не є поганою ідеєю.

Атоми призначені для незалежного стану, який потрібно синхронізувати між потоками. Якщо вам ніколи не потрібно буде одночасно змінювати стан атома і нічого іншого, використання at atom є безпечним (зокрема, якщо у всій програмі є лише один фрагмент стану, ви можете помістити його в атом) . Як нетривіальний приклад, якщо ви намагаєтеся кешувати повернені значення функції (тобто запам'ятовувати її), використання атома, ймовірно, безпечно - стан невидимий для всіх поза функцією, тому вам не потрібно хвилюватися про зміну стану всередині функції, що щось псує.

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

Vars - це коли потрібно зберігати щось за ниткою. Якщо у вас є багатопотокова програма, і кожен потік потребує свого приватного стану, поставте цей стан у вар.

Що стосується прикладів у реальному світі, якщо ви надаєте приклад того, що ви намагаєтеся зробити, ми можемо сказати вам, що використовувати.


32

Коли я вперше читав про ці типи, я також намагався зрозуміти, де я можу або повинен використати кожен з них, тож ось моя проста англійська відповідь:

Використовуйте var, коли дані не зміняться. Це відбувається щоразу, коли ви використовуєте defабо більшість функцій, які починаються з defподібних defn.

Використовуйте атом, коли у вас є один елемент, який змінюється. Прикладом може бути лічильник або вектор, до якого потрібно додати елементи.

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

Використовуйте агент, коли ви хочете, щоб щось змінилося, але вам все одно, коли. Це може бути довге обчислення або щось записування у файл або сокет. Зауважте, що з останнім слід використовувати send-off.

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


1
Велике спасибі за вашу чітку відповідь :-) Допомагає новачкам Clojure, як я, дуже багато.
gosukiwi

27

Я написав статтю з підсумком різниці між ними і допомагаю вибрати, коли використовувати який.

Поділитися станом - при використанні vars, atom, agent та refs?

Я сподіваюся, що це допоможе людям, які шукають відповіді на цю тему.

Деякі ярлики зі статті після пропозиції @tunaci:

Варс

Vars є глобальними для кожної нитки.

Не змінюйте vars після створення. Це технічно можливо, але це погана ідея з багатьох причин.

Атоми

Поділитися доступом до змінного стану для всіх потоків. Зміна відбувається синхронно. Повторіть спробу, коли інший потік змінить стан під час виконання.

Не використовуйте неідентичні функції та функції з тривалим виконанням

Агенти

Поділитися доступом до змінного стану для всіх потоків. Зміна відбувається асинхронно.

Реф

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

І блок-схема, коли використовувати яку: блок-схема

Перегляньте зображення на веб-сайті, оскільки деякі оновлення завжди можливі.

Це складна і довга тема, щоб дати повну відповідь без копії та минулої статті, тому, будь ласка, пробачте, я перенаправляю вас на веб-сайт :)


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