[HN Gopher] The Missing Manual for Signals: State Management for...
       ___________________________________________________________________
        
       The Missing Manual for Signals: State Management for Python
       Developers
        
       Author : buibuibui
       Score  : 70 points
       Date   : 2025-06-13 11:55 UTC (11 hours ago)
        
 (HTM) web link (bui.app)
 (TXT) w3m dump (bui.app)
        
       | rikafurude21 wrote:
       | 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.
        
         | troupo wrote:
         | 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
        
           | aquariusDue wrote:
           | 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/
        
           | lbreakjai wrote:
           | 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 wrote:
             | > 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.
        
           | buibuibui wrote:
           | 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!
        
         | jazzypants wrote:
         | 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
        
           | WesolyKubeczek wrote:
           | > 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?
        
             | troupo wrote:
             | 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
        
             | jazzypants wrote:
             | 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.
        
           | jauco wrote:
           | 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 wrote:
             | 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 wrote:
           | 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.
        
         | yapyap wrote:
         | look into the Java observer pattern
        
       | esafak wrote:
       | 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]
        
         | ycombiredd wrote:
         | this 404's for me
        
         | jpitz wrote:
         | 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?
        
       | twic wrote:
       | 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 wrote:
         | 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 wrote:
         | 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 wrote:
         | The module probably has its own global register and ever time
         | Computed() is called it adds to it.
        
       | jacques_chester wrote:
       | 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 wrote:
         | > 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 wrote:
           | ... 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 wrote:
             | 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 wrote:
       | 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 wrote:
         | What makes signals DAG?
         | 
         | User caution or does e.g. this lib prevents cycles?
        
       | HelloNurse wrote:
       | 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 wrote:
         | 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.
        
       | weiliddat wrote:
       | 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
        
       | cdavid wrote:
       | 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.
        
       | pvillano wrote:
       | 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
        
       ___________________________________________________________________
       (page generated 2025-06-13 23:01 UTC)