From c255e19c423f202abe4736ef9a90b790807a7f5c Mon Sep 17 00:00:00 2001 From: Yura Dupyn <2153100+omedusyo@users.noreply.github.com> Date: Fri, 13 Feb 2026 19:00:08 +0100 Subject: [PATCH] Notes on let-signal evaluation --- src/lang/SIGNAL-EXPERIMENT.md | 86 ----------------------------------- src/lang/SIGNAL.md | 56 +++++++++++++++++++++-- 2 files changed, 53 insertions(+), 89 deletions(-) delete mode 100644 src/lang/SIGNAL-EXPERIMENT.md diff --git a/src/lang/SIGNAL-EXPERIMENT.md b/src/lang/SIGNAL-EXPERIMENT.md deleted file mode 100644 index b39f6d9..0000000 --- a/src/lang/SIGNAL-EXPERIMENT.md +++ /dev/null @@ -1,86 +0,0 @@ - -```javascript -const Thing = (initState) => ({ - state: initState, - subscribers: [], - set(transform) { - const state = transform(this.state); - this.state = state; - this.subscribers.forEach(f => { - f(state); - }); - }, - get() { - return this.state; - }, - subscribe(f) { - this.subscribers.push(f); - }, - map(transform) { - const Y = Thing(this.state); - this.subscribe(x => { - Y.set(() => transform(x)); - }); - - return Y; - }, -}); - -function pair(X, Y) { - const Z = Thing([X.get(), Y.get()]); - X.subscribe(x => { - Z.set(() => [x, Y.get()]); - }); - Y.subscribe(y => { - Z.set(() => [X.get(), y]); - }); - return Z; -} - -// Comonad lift -// Signal(a), (Signal(a) -> b) -> Signal(b) - -// X: Signal(A), f: Signal(A) -> B -// Y: Signal(B) -// function extend(X, f) { -// const y0 = f(X); -// const Y = Thing(y0); -// X.subscribe(x => { -// Y.set(f(???)); I need to somehow feed it a new signal... -// // TODO: Ofcourse I can feed it `X` again, but that feels wrong... I thought -// }); -// return Y; -// } - -const count = Thing(0); -console.log("COUNT EXISTS"); - -console.log(count.get()) - -count.subscribe(x => { - console.log("count is now", x); -}); - -count.set(() => 1) -count.set(() => 2) - -const double = count.map(x => 2*x); -console.log("DOUBLE EXISTS"); - - -double.subscribe(x => { - console.log("double is now", x); -}); - -count.set(() => 3); -count.set(() => 9); - -const WTF = pair(count, double) -console.log("-> WTF EXISTS"); - -WTF.subscribe(([x, y]) => { - console.log("WTF is now ", [x, y]); -}); - -count.set(() => 13); -``` diff --git a/src/lang/SIGNAL.md b/src/lang/SIGNAL.md index fbf365d..abf4ee4 100644 --- a/src/lang/SIGNAL.md +++ b/src/lang/SIGNAL.md @@ -472,9 +472,7 @@ let-signal { ``` - -// === parametrised signals === - +# Parametrise Signals ``` // like a top-level function of type (A, B, C) -> Signal(D) @@ -483,3 +481,55 @@ fn-signal Foo(x1, x2, x3) { } ``` +# Implementation + +## Signal Env/Frame/Binding + +``` +type SignalFrame = { + pattern: ProductPattern, + expr: Signal, +} +``` + +This is almost like a signal-env. Seems useful. + +## Let-Signal binding +``` +let-signal { + x := sig-expr-0, + y := sig-expr-1 +. f(x, y) +} +``` +What happens during the evaluation of the above signal-expression? + +1. evaluate `(sig-expr-0, sig-expr-1)` to `(sig0, sig1)` and construct a signal-env + `[ x := sig0, y := sig1 ]` +2. evaluate `initVal := f(x, y) in env [ x := sig0.read(), y := sig1.read() ]` +3. construct new signal `Z := signal(initVal)` +4. make `Z` depend on `sig0` and `sig1`. + When one of them changes, push new value on `Z` that's the result of evaluation of + `f(x, y) in env [ x := sig0.read(), y := sig1.read() ]` + +Note how `Z` is a signal together with a special closure: +- body of the closure is `f(x, y)` +- the captured signal-env of the closure is `[ x := sig0, y := sig1 ]` +- `Z` depends on `(sig0, sig1)` + + +TODO: Maybe it would be better to have something like signal-values? +These can either be plain constants, +or something more complex that has dependencies... +Right now everything is forced to be `Signal`. + +``` +type Signal = +| Constant(Value) +| Closure(... ? ...) +| NamedSignal(SignalName) // ??? +``` + +But... if we allow recompilation at runtime of signals, a constant signal may become something more complex with dependencies. +That's why you always have to track dependencies - even when the original value ain't changing (atleast with the current compiled code) +