Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable data in async systems

I have a good idea of the benefits of using immutable data in my applications and I'm fairly comfortable with the idea of using these immutable structures in a simple synchronous programming environment.

There's a good example somewhere on Stack Overflow that describes managing state for a game by passing the state along in a series of recursive calls, something like this:

function update(state) {
  sleep(100)

  return update({
    ticks: state.ticks + 1,
    player: player
  })
}

We can do some arbitrary, side-effect free work in the body of the function, then we return a new state, rather than mutating the old one.

It seems fairly easy to translate this to a simple async model, in say Javascript.

function update(state) {
  const newState = {
    player,
    ticks: state.ticks + 1
  };

  setTimeout(update.bind(this, newState), 100);
}

However, as soon as we have more sources for asynchronous events, it seems to become a lot harder to manage to keep the state immutable and the functions pure.

If we add a click event to the example, we end up with code that looks like this.

window.addEventListener('click', function() {
  // I have no idea what the state is
  // because only our update loop knows about it
});

Now obviously, I don't want to mutate the state in this method, but I need to access state in order to create a new state, something like this.

window.addEventListener('click', function() {
  const state = getState();

  createState({
    player,
    clicks: clicks + 1
  });
});

But it would seem like this requires some kind of mutable state manager?

Alternatively, I suppose I could add the click event to a queue of actions to be processed within the update loop, something like:

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);
}

Again, this doesn't feel particularly functional and relies on at least some mutable state somewhere along the way. These are probably naive approaches coming from someone who has mostly worked with mutable state and imperative object oriented programming.

What does the design for a system look like when there are multiple asynchronous event sources and we want everything to be immutable? Or at least, what's a good pattern for controlling mutability in a system like this?

like image 762
Dan Prince Avatar asked Aug 20 '15 17:08

Dan Prince


People also ask

What is meant by immutable data?

Immutable data is a piece of information in a database that cannot be (or shouldn't be) deleted or modified. Most traditional databases store data in a mutable format, meaning the database overwrites the older data when new data is available.

What is the use of immutable data structures?

Immutable data structures are very handy when you want to prevent multiple people modifying a piece of data in parallel programming at same time. Mutable data structures( e.g. Array) can be changed at any time while immutable data structures cannot be.

Why is immutable data important?

Immutability allows you to track the changes that happen to these objects like a chain of events. Variables have new references that are easy to track compared to existing variables. This helps in debugging the code and building the concurrent application.

Is array immutable data type?

Arrays and Objects Are Mutable Arrays and objects are not immutable in JavaScript because they can indeed change their value over time. Let's verify this by running the following code examples in the console.


1 Answers

You might be interested in taking a look at Redux. Redux takes a similar approach:

  • It models the whole application state as a single immutable object.
  • User actions are essentially messages that are dispatched to the store for arbitrary processing.
  • Actions are handled by reducer functions in the form f(previousState, action) => newState. This is a more functional approach than your original version.
  • The store runs the reducers and maintains a single immutable application state.

You're right that this isn't strictly immutable, as the store itself has a mutable reference to the current state. But as others have noted, this doesn't seem like an issue for most conceptions of immutable data.

In addition to UI actions, you might also have a tick action that fires in a loop - it's just another input event, processed by the same set of reducers.

like image 122
nrabinowitz Avatar answered Oct 14 '22 08:10

nrabinowitz