Подтвердить что ты не робот

Clojure: когда использовать изменяемое состояние

Я реализую игру "вещь" в Clojure. До сих пор я передавал объект "мирового статуса" среди функций. Он очень "функциональный" , и я могу имитировать любой момент игры, просто подпитывая систему созданным мировым состоянием.

Так как Clojure имеет очень изощренную систему управления состоянием (ссылки, атомы...), я хотел бы знать, что является более идиоматическим способом программирования Clojure, использовать ли его систему или придерживаться более функциональный подход.

Спасибо.

EDIT:

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

4b9b3361

Ответ 1

Чистые функции уже идиоматичны Clojure. Типы ссылок (ref, atom, agent) предназначены для координации общего состояния.

Пока ничего не используется (вы не обновляете мир в одном потоке при рендеринге в другом или координируете несколько игроков в своих потоках), нет причин делиться состоянием, и, следовательно, нет оснований для отказа от чисто -функциональный стиль.

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

Ответ 2

Clojure - это язык функционального программирования, предназначенный для использования многоядерных/SMP-процессоров. Вы можете получить много из функционального языка программирования без доступа к общей памяти, и, действительно, Erlang делает это чудесно, но не использует преимущества всех процессоров.

Где clojure светит по сравнению с языками "Модель актера", когда несколько потоков хотят работать с одними и теми же данными значимым и скоординированным образом. Если у вас есть тривиально параллелизуемая проблема, например обработка изображений, вам не нужны эти преимущества, и вы можете просто отправить один кусок данных каждому работнику. Когда эти биты данных взаимозависимы, то координированный общий доступ становится реальным преимуществом.

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

Еще одна причина использовать такую ​​модель для редактирования игрового мира, кроме скорости, - это позволить вам разделять процессы, которые делают разные вещи на разные потоки в одном из примеров Rich early clojure он показывает симулятор ant, где каждый ant имеет свой собственный поток, который обновил положение муравьев на доске, что сделало для очень короткого и простого кода.

Ответ 3

Написание игры в текущем функциональном стиле уже является правильным способом, если только один поток или контекст записывают эти данные (что происходит, когда вы повторяетесь). На самом деле ключевым преимуществом для тех объектов, о которых вы говорили, является совместное использование общего состояния. Если вы хотите распараллеливать свою программу с помощью многопоточности, то использование этих инструментов может быть полезно.