我對在應用程序中使用不可變數據的好處有一個很好的想法,我對在簡單的同步編程環境中使用這些不可變結構的想法感到滿意。異步系統中的不可變數據
有堆棧溢出的某處一個很好的例子,通過一系列遞歸調用,像這樣的傳遞狀態一起描述了一個遊戲管理狀態:
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。按照定義,事件是有狀態的;根據定義,輸入是可變的。你可以做的最好的事情是儘可能地將可變狀態從不可變狀態中分離出來。隊列實際上運行良好(特別是從遊戲的角度來看;我自己也使用過),所以對於你的情況,隊列可以是可變的 - 你可以繼續添加事件 - 直到下一次更新運行。此時,您需要創建一個不可變的隊列副本。之後,你可以堅持不變的構造。 –