jacques_chester 15 hours ago
This triggered some associations for me.

Strongest was Cells[0], a library for Common Lisp CLOS. The earliest reference I can find is 2002[1], making it over 20 years old.

Second is incremental view maintenance systems like Feldera[2] or Materialize[3]. These use sophisticated theories (z-sets and differential dataflow) to apply efficient updates over sets of data, which generalizes the case of single variables.

The third thing I'm reminded of is Modelica[4], a language where variables are connected by relations (in the mathematical sense). So while A = B + C can update A on when B or C change, you also can update just A and B, then find out what C must have become.

[0] https://cells.common-lisp.dev

[1] https://web.archive.org/web/20021216222614/http://www.tilton...

[2] https://www.feldera.com

[3] https://materialize.com

[4] https://modelica.org

mananaysiempre 13 hours ago
> Strongest was Cells[0], a library for Common Lisp CLOS. The earliest reference I can find is 2002[1], making it over 20 years old.

How about Microsoft DirectAnimation[1] from 1998, literally designed under the direction of Conal Elliott? Serious question, for what it’s worth, I’ve always wondered if all discussions of this thing are lost to time or if nobody cared for it to begin with.

[1] http://sistemas.afgcoahuila.gob.mx/software/Visual%20Basic%2...

PaulHoule 13 hours ago
... or Visicalc, TK/Solver, etc.

I've always been baffled that people think spreadsheets are like dataframes when the really interesting thing has always been you can write formulas that refer to each other and the engine figures out the updating. Most of the times I've written a spreadsheet I haven't used the grid as a grid but just a place I can write some labels, some input fields and formulas.

cdavid 11 hours ago
well it is both an easy way to compute in a dataframe context and a reactive programming paradigm. When combined, it gives a powerful paradigm for throwing data-driven UI, albeit non scalable (in terms of maintenance, etc.).
awkii 15 hours ago
What the author touches on with before and after "declarative thinking" is largely applicable to all Directed Acyclic Graph (DAG) workflows, and not just signals. They are 100% correct that there is a mental shift. Yes, you can use magic to implicitly declare your DAGs with signals. You can also be really explicit with dependencies.

DAG-based workflows incur a cost in terms of complexity, but there are a few advantages to using DAGs instead of sequential.

1. Parallelism becomes inherently built-in

2. It's easier for a new developer to understand the direct dependencies of a node on other nodes (compared to sequential). Sometime in the future, a developer may want to split off a task or move it up/downstream of other tasks.

3. Fault tolerance & recovery becomes easier. Just because 1 step fails, doesn't mean that the whole workflow must come to a halt.

coldtea 9 hours ago
What makes signals DAG?

User caution or does e.g. this lib prevents cycles?

PeterStuer 1 hour ago
I've designed something like this before but in the context of orchestration. A 'read' implicitly became a subscription in the meta-process and any subsequent changes to the consumed value triggered updates to the consumer process that were either explicitly caught or handled through an implicit context process.

This allowed process definitions to remain simple enough for business analysts to comprehend while still able to cover real world complexity.

twic 17 hours ago

  y = Computed(lambda: calculate_y(x()))
How does this instance of Computed know that it depends on x? Does it parse the bytecode for the lambda? Does it call the lambda and observe which signals get accessed?

In my homebrew signal framework, which emerged in the middle of a complicated web dashboard, this would look like:

  y = Computed([x], calculate_y)
So the machinery gets to see the signal directly.
buibuibui 16 hours ago
I am using the standard Python library `contextvars.ContextVar` as the foundation of my reactivity system's dependency tracking mechanism. In the computation step, when Signals get accessed, I track them as dependencies.
TOGoS 15 hours ago
I've used systems that did this (some TypeScript TUI library comes to mind) and was similarly confused. I think what actually happened was that the x function/getter/whatever had some 'magic' in it that let it communicate with `Computed` as a side-effect of `Computed` computing the value.

Too magical for me. I'd rather have something like you described where inputs are explicit, so I don't have to guess about whether the magic will work in any given case.

TeeMassive 9 hours ago
The module probably has its own global register and ever time Computed() is called it adds to it.
cdavid 12 hours ago
One of the largest, if not the largest python codebase in the world, implements similar ideas to model financial instruments pricing: https://calpaterson.com/bank-python.html.
rikafurude21 18 hours ago
I've been writing front-end javascript the "just use functions" way and never really wanted to get into React because it looks too complicated. But this makes sense. God damn it I want to actually learn react now.
jazzypants 17 hours ago
This article never mentions React. This has nothing to do with React. There's a reason people say "react is not reactive"[1].

Signals are derived from Observables[2] which were first used in Adam Haile's S.JS[2] and made popular in JavaScriptLand by Ryan Carniato's SolidJS[3].

[1] - https://dev.to/this-is-learning/how-react-isn-t-reactive-and...

[2] - https://dev.to/this-is-learning/the-evolution-of-signals-in-...

[3] - https://www.solidjs.com/

[4] - https://github.com/adamhaile/S

jauco 14 hours ago
Fwiw knockoutjs seems to predate s.js (2010 vs 2013)

I can’t remember if at that point it was the first lib to uses observables.

jazzypants 9 hours ago
Oof! I can actually still see a link to Knockout.js in my clipboard, so I clearly meant to add it as a source for that post. I also got the numbering all wrong, so I guess I should have spent another minute checking it for accuracy.

Thanks for the correction so that other people can learn!

Izkata 10 hours ago
Since GP mentioned React, I think MobX was more popular there and seems to predate SolidJS. Also, Valtio is a modern version of the same idea but with a lot less boilerplate.
WesolyKubeczek 14 hours ago
> made popular in JavaScriptLand by Ryan Carniato's SolidJS[3]

Are you sure it hadn't been, by chance, made popular even before by KnockoutJS?

jazzypants 9 hours ago
Yeah, as I said in response to another commenter, I actually had a link to Knockout in my clipboard. I'm pretty sure I was supposed to add the link after the word Observable.
troupo 12 hours ago
Actual popularity to the point that they are now being adopted into the standard (not to say all frameworks except React) came thanks to Ryan. Though he explicitly acknowledges that original ideas come from Knockout, S and Marko
troupo 18 hours ago
React is very far from signals (and very far from sane state management). Better alternatives:

- SolidJS (kickstarted the whole signals revolution)

- Svelte

- Preact (and Preact Signals)

- Well, even Angular got signals now

buibuibui 16 hours ago
I actually created the library after being exposed to Angular Signals starting from the v16 release. I watched some talks and read articles about Signals, just to know about Ryan Carniato from SolidJS. He did an excellent job teaching the world about Signals!
lbreakjai 16 hours ago
React doesn't really make many assumptions regarding state management. You're free to pick the library you want. Redux used to be the standard, but I worked on applications purely using RxJS, the way signals are presented in this article.
troupo 12 hours ago
> You're free to pick the library you want.

They are all still pretty hampered by React's model: re-render (internally, in VDOM) the whole component on any minor change.

aquariusDue 17 hours ago
There's also Datastar that uses signals and ends up being the best of HTMX and Alpine.js combined (at a smaller bundle size too).

https://data-star.dev/

yapyap 17 hours ago
look into the Java observer pattern
HelloNurse 15 hours ago
Two perplexing aspects:

- Why so many lambda functions instead of regular named functions? Is it a technical limitation? Something important should have a name, for instance (for the example in the article) different ways to compute greetings from names.

- How are the computations ordered, particularly multiple Effects that trigger at the same change? For instance, in the example in the article, when the name changes the updated greeting is printed before or after the updated location.

buibuibui 13 hours ago
You can use normal names function instead of lambdas if you prefer! In Javascript anonymous functions are used normally for things, where defining named functions are considered too verbose - I use lambdas for that in Python.

The Signals evaluation are topologically ordered and are running synchronously. Effects are running in the order they are defined.

pvillano 10 hours ago
I have a dream for a compiled reactive DSL for video game programming that makes replay and rollback netcode automagically, eliminates bugs in state management, and naturally expresses derived state and the simulation step/transition function, while still being performant enough for real time

The performance hit from all that indirection of registering, getters, setters, discover, traversal, and lambdas could be avoided if we could compile the dag into smartly nested ifs

weiliddat 13 hours ago
Hmm I have mixed feelings about this. I've thought about this topic for a bit, a couple of years ago I thought of bringing functional reactive programming to a backend node.js project (partially because of managing callback hell); in the past couple of years I work on an event/workflow system with 100+ million events per day.

This feels like a lighter weight alternative to Temporal or other workflow tools[0], but eventually for a backend system you'd likely be rebuilding features that are tailored for the backend.

In frontend code, you have many side effects (e.g. DOM, styling) that rely on a single piece of data/event, and more side effects that rely on those side effects (e.g. component hierarchy), and having this laid out declaratively is one way to understand the behavior of an application when this piece of data changes. You are also almost never concerned about durability/persistence of the state of data on the frontend, just because the code interacts with the browser and we almost never question the reliability of that API. A human is typically the "driver" of these interactions and is typically in the loop for most interactions, so stuff that fails, e.g. a failed network call, can bubble up to the user to deal with.

Conversely, web backend projects have code and infrastructure that are distributed (even monolithic ones), and most of the time are concerned with persisting state/data, distributing/scheduling workloads, etc. Each side effect / computation, especially ones that cross networks/service, has its own requirements for whether it should be at least once/at most once, retried/retry patterns, latency/throughput, failure modes/error handling. These requirements also define your boundaries/interfaces, rather than a nice semantic and declarative one (not exclusive but oftentimes the requirements win out).

Not saying that this signal-based approach can't be used in some areas of the application would benefit for declarative computation, but the examples given seem to indicate also a desire to do distributed workflow stuff.

[0] https://temporal.io/, https://github.com/meirwah/awesome-workflow-engines

esafak 18 hours ago
For bigger workflows, this declarative pattern is already implemented by orchestrators like Dagster, Flyte, and recently Airflow; e.g., https://dagster.io/blog/declarative-scheduling [fixed]
jpitz 12 hours ago
Are you talking about Airflow Datasets and data-aware scheduling?

https://airflow.apache.org/docs/apache-airflow/2.4.0/release...

Isn't that about as recently as Dagster?

esafak 8 hours ago
Yes, asset-aware scheduling.
ycombiredd 17 hours ago
this 404's for me