Замыкание различий между Ref, Var, Agent, Atom, с примерами - PullRequest
102 голосов
/ 03 февраля 2012

Я очень новичок в Clojure. Можете ли вы, ребята, дать мне объяснения со сценариями реального мира. Я имею в виду, где использовать Ref, Var, Agent, Atom. Я читал книгу, но все еще не мог понять примеры из реальной жизни.

Ответы [ 5 ]

161 голосов
/ 04 февраля 2012

Я настоятельно рекомендую «Радость Clojure» или «Программирование Clojure» для реального ответа на этот вопрос, я могу воспроизвести краткий отрывок из мотивации для каждого:

начать с просмотра это видео о понятии идентичности и / или , изучаемом здесь .

  • Ссылки предназначены для координированного синхронного доступа ко "многим удостоверениям".
  • Атомы предназначены для Несогласованный синхронный доступ к одному идентификатору.
  • Агенты предназначены для Несогласованный асинхронный доступ к одному идентификатору.
  • Вары предназначены для локальных потоков изолированные идентификаторы с общим значением по умолчанию.

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

Несогласованный доступ используется, когда требуется обновить только одну личность, это очень распространенный случай.

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

Асинхронный доступ is "запустить и забыть"и пусть Идентичность достигнет своего нового состояния в свое время.

38 голосов
/ 03 февраля 2012

Refs для состояния, которое должно быть синхронизировано между потоками. Если вам нужно отслеживать кучу разных вещей, и вам иногда нужно будет выполнять операции, которые записывают сразу несколько вещей, используйте refs. Каждый раз, когда у вас есть несколько разных частей состояния, использование ссылок не является плохой идеей.

Атомы для независимого состояния, которое должно быть синхронизировано между потоками. Если вам никогда не понадобится изменять состояние атома и все остальное одновременно, использование at Atom безопасно (в частности, если во всей программе имеется только один фрагмент состояния, вы можете поместить его в атом) , В качестве нетривиального примера, если вы пытаетесь кэшировать возвращаемые значения функции (то есть запомните его), использование атома, вероятно, безопасно - состояние невидимо для всего, что находится за пределами функции, поэтому вам не нужно беспокоиться об изменении состояния внутри функции что-нибудь испортило.

Первичная точка агентов заключается в том, что они работают в другом потоке. Вы можете получить значение агента и указать ему применить функцию к его значению, но вы не знаете, когда функция будет запущена или к какому значению будет применена функция.

Вары предназначены для случаев, когда вам нужно что-то хранить для каждого потока. Если у вас многопоточная программа, и каждый поток нуждается в собственном частном состоянии, поместите это состояние в переменную.

Что касается примеров из реального мира, если вы предоставите пример того, что вы пытаетесь сделать, мы можем сказать вам, что использовать.

29 голосов
/ 19 июля 2014

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

Используйте переменную, когда данные не изменятся.Это происходит всякий раз, когда вы используете def или большинство функций, которые начинаются с def, например defn.

. Используйте атом, если у вас есть один изменяемый элемент.Примером может быть счетчик или вектор, к которому вы хотите добавить элементы.

Используйте ссылку, если у вас есть две или более вещи, которые должны измениться одновременно.Подумайте «транзакции с базой данных», если вы знакомы.Каноническим примером этого является перевод денег с одного счета на другой.Каждая учетная запись может быть сохранена в одной ссылке, чтобы изменения можно было сделать атомарными.

Используйте агента, когда хотите что-то изменить, но когда вам все равно.Это может быть длительное вычисление или запись чего-либо в файл или сокет.Обратите внимание, что с последним вы должны использовать send-off.

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

22 голосов
/ 15 апреля 2016

Я написал статью с кратким изложением разницы между ними и помогу выбрать, когда использовать какую.

Состояние общего ресурса - когда используются переменные, атомы, агенты и ссылки?

Я надеюсь, что это поможет людям, ищущим ответы в этой теме.

Некоторые ссылки из статьи после предложения @tunaci:

Vars

Вары являются глобальными для всех потоков.

Не меняйте вары после создания.Технически это возможно, но это плохая идея по многим причинам.

Атомы

Предоставить общий доступ к изменяемому состоянию для всех потоков.Изменение происходит синхронно.Повторите попытку, когда другой поток изменит состояние во время выполнения.

Не используйте не идемпотентные функции и функции с длительным выполнением

Агенты

Предоставить общий доступ к изменяемому состоянию для всех потоков.Изменение происходит асинхронно.

Refs

Refs работает аналогично транзакциям базы данных.Пишите и читайте защищены в dosync.Вы можете работать со многими ссылками, безопасными в транзакции.

И блок-схема при использовании которой: flowchart

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

Это сложная и длинная тема, чтобы дать полный ответ без копирования и прошлой статьи, поэтому, пожалуйста, прости меня, я перенаправляю тебя на сайт:)

4 голосов
/ 11 января 2014

атомы, ссылки и агенты - немного освещения здесь http://blog.jayfields.com/2011/04/clojure-state-management.html

...