У меня есть хорошее представление о преимуществах использования неизменяемых данных в моих приложениях, и я довольно доволен идеей использования этих неизменяемых структур в простой синхронной среде программирования.Неизменяемые данные в асинхронных системах
Там хороший пример где-то на переполнение стека, который описывает управление состоянием для игры, передавая состояние вместе в серии рекурсивных вызовов, что-то вроде этого:
function update(state) {
sleep(100)
return update({
ticks: state.ticks + 1,
player: player
})
}
Мы можем сделать некоторые произвольные, побочные эффект свободной работы в теле функции, то мы возвращаем новое состояние, а не мутируем старое.
Кажется довольно легко перевести это на простую асинхронную модель, например, на Javascript.
function update(state) {
const newState = {
player,
ticks: state.ticks + 1
};
setTimeout(update.bind(this, newState), 100);
}
Однако, как только у нас есть больше источников для асинхронных событий, кажется, становится намного сложнее, чтобы суметь сохранить состояние неизменным и функция чистыми.
Если мы добавим событие click к примеру, мы получим код, который выглядит следующим образом.
window.addEventListener('click', function() {
// I have no idea what the state is
// because only our update loop knows about it
});
Теперь, очевидно, я не хочу, чтобы мутировать состояние в этом методе, но мне нужно, чтобы получить доступ к государству, чтобы создать новое состояние, что-то вроде этого.
window.addEventListener('click', function() {
const state = getState();
createState({
player,
clicks: clicks + 1
});
});
Но, похоже, для этого требуется какой-то изменчивый государственный менеджер?
Кроме того, я полагаю, я мог бы добавить событие щелчка в очереди действий, подлежащих обработке в течение цикла обновления, что-то вроде:
window.addEventListener('click', function() {
createAction('click', e);
});
function update(state, actions) {
const newState = {
player,
ticks: state.ticks + 1,
clicks: state.clicks + actions.clicks.length
};
setTimeout(update.bind(this, newState, []), 100);
}
Опять же, это не чувствует себя особенно функциональным и опирается на в по крайней мере, какое-то изменчивое состояние где-то в пути. Вероятно, это наивные подходы, исходящие от человека, который в основном работал с изменчивым государственным и императивным объектно-ориентированным программированием.
Как выглядит дизайн системы, когда есть несколько асинхронных источников событий, и мы хотим, чтобы все было неизменным? Или, по крайней мере, что является хорошей моделью для управления изменчивостью в такой системе?
Вы ищете функциональное реактивное программирование (FRP). – Bergi
Эта очередь действительно звучит как разумный способ (просто не забудьте очистить ее после того, как вы ее использовали в 'update'). Но на самом деле вам всегда нужно, чтобы небольшая часть вашей программы была изменчивой, потому что событие, подобное щелчку *, должно иметь побочный эффект (или вообще ничего не делает). Immutabiltity не о том, чтобы никогда ничего не делать в вашей программе, это разумное моделирование того, что вы делаете. – Bergi
Согласен с @Bergi. События по определению являются состояниями; вход, по определению, изменчив. Лучшее, что вы можете сделать в своем случае, - попытаться изолировать изменчивое состояние от неизменяемого состояния как можно больше. Очередь действительно работает хорошо (особенно с точки зрения игры, я сам ее использовал), и поэтому в вашем случае очередь может быть изменчивой - вы можете продолжать добавлять события - UNTIL запускается следующее обновление. В этот момент вам нужно сделать неизменяемую копию очереди. После этого вы можете придерживаться непреложных конструкций. –