Как вы можете заставить неизменность функционального программирования на столе тральщика? - PullRequest
1 голос
/ 09 января 2020

Я много читаю о функциональном программировании и неизменяемости, и у меня возникла небольшая проблема с пониманием того, как можно создать даже простую игру тральщика, не изменяя состояние? Очевидно, что у вас есть начальное состояние таблицы тральщика в массиве ([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(0);
console.log(minesweeperTable2x2); // [1,0,1,0]
revealTile(1);
console.log(minesweeperTable2x2); // [1,1,1,0]
revealTile(3);
console.log(minesweeperTable2x2); // [1,1,1,1]

Есть ли кто-нибудь, кто занимается функциональным программированием и неизменяемостью и может объяснить мне это путем преобразования кода, в который я написал парадигма функционального программирования, уважающая полную неизменность ???

Ответы [ 3 ]

1 голос
/ 09 января 2020

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

  1. Создать копию объекта
  2. Изменить копию
  3. Заменить оригинал на копию

В случае обновления одного элемента массива простая реализация будет выглядеть следующим образом:

function revealTile(table, tileNumber) {
  const nextTable = table.slice(); // create a copy
  nextTable[tileNumber] = 1; // update the copy
  return nextTable; // return the copy
}

let table = [0,0,0,0];

table = revealTile(table, 1);
console.log(table);

table = revealTile(table, 2);
console.log(table);

table = revealTile(table, 0);
console.log(table);

table = revealTile(table, 3);
console.log(table);
1 голос
/ 09 января 2020

Вы можете пересоздавать таблицу каждый раз, когда вызывается 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);

Таким образом, вы не изменяете состояние, но создаете новое состояние при каждом изменении должно произойти, а затем передать новое состояние везде, где его нужно использовать.

0 голосов
/ 09 января 2020

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

const revealTile = (n, minesweeper) => minesweeper.map(
  (value, i) => i === n ? 1 : value,
);

// ### ----

const minesweeper = [0, 0, 0, 0];

console.log(minesweeper); // [0,0,0,0]

console.log(
  revealTile(2, minesweeper),
); // [0,0,1,0]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...