-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Related Issue #50
Ref. Observable Mutable
Ref. Observable Framework Mutable
Ref. Observable Framework Converting Mutable
Ref. Observable Notebook Kit Source
Ref. Add Observable Plot Attribution to Mosaic
Given this code snippet:
let a = 0;
a += 1;
echo(a);If we transpile to the following snippet, it won't work. Because outside the codeblock defining a mutable, it's just a normal value, without value property:
const a = __mutable__(0);
a.value += 1; // a.value is undefined
echo(a); // 1What if we expose a setter from the defining place? It still doesn't work as expected. The block setA(a+1) results in incrementing forever. Because it reference a and mutate a, and every block referencing a reruns when a is mutated.
const [a, setA] = (() => {
const a = __mutable__(0);
return [a, (value) => a.value = value];
})();
setA(a + 1);
echo(a);How about we expose a setter as well? It works. Because setA(getA() + 1); doesn't reference a anymore!
const [a, setA, getA] = (() => {
const a = __mutable__(0);
return [a, (value) => a.value = value, () => a.value];
})();
setA(getA() + 1);
echo(a);In order to make mutable more transpiling-friendly, changes API a little bit. Then converts a to mutator$$a.value.
const [a, mutator$$a] = __mutator__(0);
mutator$$a.value += 1;
echo(a);But this brings another question: When should we transpile a to mutator$$a.value, and when should we leave it as is?
We can't transpile all of them to mutator$$[NAME].value, because they are not reactive anymore.
let a = 0;
setTimeout(() => {
a += 1;
}, 1000);
echo(a); // !!!! 0 instead of 1
// ------------------>
const [a, mutator$$a] = __mutator__(0);
setTimeout(() => {
mutator$$a.value += 1;
}, 1000);
echo(mutator$$a); // mutator$$a is not a mutable My intuition is that if a codeblock mutates the mutatble, then transpile it, otherwise don't. But what if a block mutates and references a mutable:
let a = 0;
setTimeout(() => {
a *= 10;
}, 1000);
{
a += 1;
echo(a); // !!! 1 instead of 11
}This will not work as expected either. So I guess we should discourage this usage? Because you can always split them up:
let a = 0;
setTimeout(() => {
a *= 10;
}, 1000);
a += 1;
{
echo(a); // 10
}