我正在阅读有关函数式编程和不变性的很多文章,并且在理解如何通过不改变状态来制作甚至是一个简单的扫雷游戏时遇到了一个问题。显然,您在数组中具有minesweeper表的初始状态([0,0,0,0]-所有图块均被隐藏)。但是,如果您不记录状态变化([0,0,1,0]-第二行中的第一个图块已打开),如何显示图块?
这里是我所说的简单例子:
let minesweeperTable2x2 = [0,0,0,0];
let revealTile = ( tileNumber ) => {
minesweeperTable2x2[tileNumber] = 1;
}
console.log(minesweeperTable2x2); // [0,0,0,0]
revealTile(2);
console.log(minesweeperTable2x2); // [0,0,1,0]
有没有从事函数式编程和不变性的人,可以通过将我编写的代码转换为函数式编程范例,并尊重完全不变性,向我解释这一点?
您可以在每次调用revealTile
时重新创建表,并使用该新表,直到需要再次更新它为止:
const initialTable = { ...[0,0,0,0] };
const revealTile = (lastTable, tileNumber) => {
return { ...lastTable, [tileNumber]: 1 };
};
console.log(initialTable);
const nextTable = revealTile(initialTable, 2);
console.log(nextTable);
以一个稍微复杂的代码段为例,该代码段将运行到显示数组的所有项目为止:
const initialTable = { ...[0,0,0,0] };
const revealTile = (lastTable, tileNumber) => {
return { ...lastTable, [tileNumber]: 1 };
};
const iter = (currentTable) => {
const indexToReveal = prompt('Index to reveal? Currently ' + Object.values(currentTable));
const num = parseInt(indexToReveal);
if (indexToReveal === null || indexToReveal < 0 || indexToReveal > 3) {
throw new Error();
}
const nextTable = revealTile(currentTable, indexToReveal);
if (Object.values(nextTable).every(val => val === 1)) {
console.log('Filled');
} else {
iter(nextTable);
}
}
iter(initialTable);
这样,您不是mutating状态,而是在每次需要发生更改时创建一个new状态,然后将新状态传递到需要使用的所有地方。