🏠 back to Observable

Cell memoization

Or, is there a canonical way to only update a cell if the dependencies actually change?

See the “changed” indicator stays activated every frame, instead of once per second:

There’s not a general way to ignore changes: when a cell changes, everything downstream of that cell will be re-evaluated (even if the new cell’s value is equal to the old one, say per the same-value-zero algorithm).

So, if you want something to update once a second, you would do it like this:

seconds = {
  while (true) {
    const seconds = Math.ceil((Date.now() + 1) / 1000) * 1000;
    yield Promises.when(seconds, seconds);
  }
}

Or if you don’t care about the value:

tick = {
  while (true) {
    yield Promises.tick(1000);
  }
}

Then you could say:

tick, Math.floor(performance.now() / 1000)

That said, you can “cheat” out of simple dataflow using mutables — but we don’t typically recommend this, as it’s often simpler if you use a strategy like the above. With mutables, you can selectively assign a new value:

mutable elapsed = 0
update = {
  now;
  const e = Math.floor(performance.now() / 1000);
  if (e !== mutable elapsed) mutable elapsed = e;
}

In addition to being more complicated, it’s also slower, as the update cell has to run sixty times a second to check whether it should mutate the value of elapsed. The seconds approach above, in contrast, will sleep efficiently using setTimeout.

Here’s a related discussion:

I have an animation with 2 layers: with one layer that changes at 60fps, and one that changes less often than that. I think the mutable flow will work for that.

Here’s the output of that:

Specifically, the background triangle grid only updating when needed: #triIndexUpdater

1 Like