DEV Community

Discussion on: The Quest for ReactiveScript

Collapse
 
webreflection profile image
Andrea Giammarchi

I've played around this topic a bit myself, and the gist was something like this:

const invoke = $ => $();
const signal = value => function $() {
  if (arguments.length) {
    value = arguments[0];
    if (effects.has($))
      effects.get($).forEach(invoke);
  }
  return value;
}

const effects = new WeakMap;
const effect = (callback, $$) => {
  const fx = () => callback(...$$.map(invoke));
  for (const $ of $$) {
    if (!effects.has($))
      effects.set($, []);
    effects.get($).push(fx);
  }
  fx();
  return fx;
};
Enter fullscreen mode Exit fullscreen mode

This basically lets one compose values as effects too, example:

const a = signal(1);
const b = signal(2);
const c = effect((a, b) => a + b, [a, b]);

console.log(a(), b(), c()); // 1, 2, 3

a(10);
console.log(a(), b(), c()); // 10, 2, 12

b(7);
console.log(a(), b(), c()); // 10, 7, 17
Enter fullscreen mode Exit fullscreen mode

My thinking is that a variable that effects from others won't ever directly change itself, so that setting c(value) might, instead, throw an error.

As for the syntax, I find the reactive bit being well represented by functions so that let b <- a + 3; doesn't look too bad:

  • it's broken syntax these days, so it can be used/proposed
  • it is the equivalent of () => a + 3; except it accepts zero arguments as it cannot be directly invoked, and the arrow points at the reference that should reflect whatever the body/block returns.