Я очень новичок в Clojure. Можете ли вы, ребята, объяснить мне сценарии реального мира. Я имею в виду, где использовать Ref, Var, Agent, Atom. Я читал книгу, но все еще не мог понять примеры реального мира.
Clojure различия между Ref, Var, Agent, Atom, с примерами
Ответ 1
Я очень рекомендую "Радость от Clojure" или "программирование Clojure" для реального ответа на этот вопрос, я могу воспроизвести краткое описание его мотивов:
начните с просмотра этого видео по понятию Identity и/или здесь > .
- Refs для Скоординированный синхронный доступ к "многим идентификаторам".
- Атомы для Неконсолидированный синхронный доступ к одной Identity.
- Агенты для Неконсолидированный асинхронный доступ к одной Identity.
- Vars для локальных локальных локальных идентификаторов с общим значением по умолчанию.
Доступ к координированному используется, когда две идентичности должны меняться вместе, классический пример - перенос денег с одного банковского счета на другой, он должен полностью или полностью перемещаться.
Некоординированный доступ используется, когда требуется обновлять только один Identity, это очень распространенный случай.
Доступ к синхронному используется, когда ожидается, что вызов будет ждать, пока все идентификаторы не будут установлены до продолжения.
Асинхронный доступ - это "огонь и забыть", и пусть Identity достигнет своего нового состояния в свое время.
Ответ 2
Refs - это состояние, которое необходимо синхронизировать между потоками. Если вам нужно отслеживать кучу разных вещей, и вам иногда потребуется выполнять операции, которые пишут сразу нескольким вещам, используйте ссылки. Каждый раз, когда у вас есть несколько разных состояний, использование ссылок не является плохой идеей.
Атомы предназначены для независимого состояния, которое необходимо синхронизировать между потоками. Если вам никогда не понадобится изменять состояние атома и что-то еще в одно и то же время, использование в атоме является безопасным (в частности, если во всей программе есть только одна часть состояния, вы можете поместить его в атом), В качестве нетривиального примера, если вы пытаетесь кэшировать возвращаемые значения функции (например, memoize), использование атома, вероятно, безопасно - состояние невидимо для всего вне функции, поэтому вам не нужно беспокоиться о смене состояния внутри функции, что-то испортить.
Первоочередной задачей агентов является то, что они запускаются в другом потоке. Вы можете получить значение агента и указать ему, чтобы применить функцию к ее значению, но вы не знаете, когда будет работать функция или какое значение будет применено к функции.
Vars предназначены, когда вам нужно хранить что-то по отдельности. Если у вас многопоточная программа, и каждый поток нуждается в собственном приватном состоянии, поместите это состояние в переменную.
Что касается примеров в реальном мире, если вы представляете пример того, что вы пытаетесь сделать, мы можем сказать вам, что использовать.
Ответ 3
Когда я впервые прочитал об этих типах, я также попытался понять, где я могу или должен использовать каждый из них, поэтому вот мой простой английский ответ:
Используйте var, когда данные не будут изменены. Это происходит всякий раз, когда вы используете def
или большинство функций, начинающихся с def
, например defn
.
Используйте атом, если у вас есть один элемент, который изменяется. Примером может быть счетчик или вектор, для которого вы хотите добавить элементы.
Используйте ref, если у вас есть две или более вещи, которые должны меняться одновременно. Подумайте "транзакции с базой данных", если вы знакомы. Канонический пример этого - перенос денег с одного счета на другой. Каждая учетная запись может быть сохранена в ref, чтобы можно было изменить атомы.
Используйте агент, если вы хотите что-то изменить, но вам все равно, когда. Это может быть длинное вычисление или запись чего-либо в файл или сокет. Обратите внимание, что с последним вы должны использовать send-off
.
Примечание. Я ценю, что для каждого из них гораздо больше, но, надеюсь, это должно дать вам отправную точку.
Ответ 4
Я написал статью с резюме разницы между ними и помочь выбрать, когда использовать какой.
Share state - при использовании vars, атомов, агентов и ссылок?
Я надеюсь, что это поможет людям найти ответы в этой теме.
Некоторые ярлыки из статьи после предложения @tunaci:
Варс
Vars являются глобальными для каждого потока.
Не изменяйте vars после создания. Это технически возможно, но это плохая идея по многим причинам.
Атомы
Предоставить доступ к изменяемому состоянию для каждого потока. Изменения происходят синхронно. Повторите попытку, когда другой поток изменит состояние во время выполнения.
Не используйте идемемпотентные функции и функции с большим временем выполнение
Агенты
Предоставить доступ к изменяемому состоянию для каждого потока. Изменения происходят асинхронно.
Refs
Refs работает подобно транзакциям базы данных. Запись и чтение защищать в досинк. Вы можете работать со многими refs safe в транзакции.
И блок-схема, при использовании которой:
Пожалуйста, посмотрите изображение на веб-сайте, потому что некоторые обновления всегда возможны.
Это сложная и длинная тема, чтобы дать полный ответ без копирования и прошлой статьи, поэтому, пожалуйста, простите меня, я перенаправляю вас на сайт:)
Ответ 5
атомы, refs и агенты - некоторое освещение здесь http://blog.jayfields.com/2011/04/clojure-state-management.html