Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fine-grained reactivity #80

Open
5 tasks
edemaine opened this issue Aug 1, 2022 · 0 comments
Open
5 tasks

Fine-grained reactivity #80

edemaine opened this issue Aug 1, 2022 · 0 comments

Comments

@edemaine
Copy link
Owner

edemaine commented Aug 1, 2022

There are two scenarios where we'd like to avoid evaluating a symbol mapping:

  1. In regular single-pass, we could detect that the second occurrence of a symbol X is the same as the first occurrence, so we could re-use the previous SVG.
  2. In the GUI, if one symbol changes, ideally we'd know which other symbols need to be updated, instead of having to recompute the SVG for every symbol.

As of this writing, this is done with "static symbols" that are independent of any context, but which are tricky to declare and probably somewhat rare as a result, and will change a bit in #13. But we can do better with the idea of fine-grained reactivity from e.g. SolidJS and Maverick (and maybe we can even use such libraries directly instead of building something new).

  • Use of context.i and/or context.j indicates dependence on coordinate(s). If using both, must be computed in all cases. If using one, can be re-used in row or column. If none, can always be re-used (except for other rules below).
  • Use of svgtiler.memo(() => (context.i + context.j) % 2) depends on the parity of the coordinates, but not the individual coordinates.
  • Use of context.neighbor(...) (or context.at of at context method #78) depends on key of that neighbor. Otherwise, assume independent of that neighbor.
  • For side-effects via global variables, need to use [signal, setSignal] = createSignal(() => []) (or some other interface). The initializer gets called for every drawing (or maybe needs to be wrapped in onNewDrawing Callback when starting a new drawing #79).
  • Use of svgtiler.untrack(() => ...) to use data without being reactive to it. Similar to svgtiler.static from Generalized mappings / Top-level function #13 used at top level, but needs function wrapper?

This is all kind of different from standard reactive libraries, which call a function once to detect dependencies and recall it when one of those dependencies change. Here we have several calls to the same function (for multiple instances of the same symbol X), and we'd like to memoize their return value for the data they use, so that the next call doesn't even happen if the data matches. Hmm, but multiple calls might depend on different data, so the cache data structure is a bit weird.

Alternatively, we could just try to handle the dynamism from the GUI, in which case this resembles other fine-grained systems very closely (and in single-pass mode, fine-grained reactivity could be disabled). But this would make shift/rotate/etc. operations inefficient without additional effort (though we could also just do that effort).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant