It looks like we are going to keep reinventing dataflow constraints[1] over and over again, always with slightly different terminology (Rx, FRP, signals, ...)<p>So it (a) appears to be a very useful or at least attractive concept, and (b) somehow difficult to fit into current programming languages/practice in a clean way.<p>[1] <a href="https://blog.metaobject.com/2014/03/the-siren-call-of-kvo-and-cocoa-bindings.html" rel="nofollow">https://blog.metaobject.com/2014/03/the-siren-call-of-kvo-an...</a> (HN: <a href="https://news.ycombinator.com/item?id=7404149" rel="nofollow">https://news.ycombinator.com/item?id=7404149</a> )
It's interesting how every build system, frontend framework, programming language implements its own promise pipeline/delayed execution/observables/event propagation.<p>But the implementations are rarely extracted out for general purpose usage and rarely have a rich API.<p>I've been thinking a lot about a general purpose "epoll" which be registered on objects that change. I want to be able to register a reaction to a sequence of actions on arbitrary objects with an epoll style API.<p>One of my ideas is GUI thunking. The idea that every interaction with the GUI raises a new type that can be interacted with, to queue up behaviours on the GUI. This is essentially Future<> that are typed and the system reacts to the new type based on what you did and presents a GUI that is as if the operation you queued up was completed. (You can interact with the future because any action on something that isn't done yet, is queued up)<p>It's a bit like terraform plan and apply, but applied to general purpose GUIs.<p>For example, you can click download file, then queue up installation and then using the application, ALL BEFORE it is installed. Because the actual computation is separate from the type information that was queued up.<p>Imagine using AWS Console to set up an entire infrastructure and wire everything together but not actually execute anything until the very end when you click "Run".<p><a href="https://github.com/samsquire/gui-thunks">https://github.com/samsquire/gui-thunks</a><p>I feel we are still early days with regard how to build computer user interfaces that are easy to build, maintain and understand the code for.<p>I used knockout and angularjs 1 and I enjoyed Knockout especially. ko.observables and the map plugin makes creating reactive code very straightforward.
Not sure I like the mixed push/pull approach. If you're already traversing the tree to mark nodes as possibly dirty, you might as well recompute the node's value and store it while you're there. Otherwise on pull/lazy update, you're traversing the tree all over again! Terrible for cache locality, particularly for large graphs.<p>You might be tempted to say that the lazy approach might avoid some recomputations, but if a node isn't actually going to be accessed then that node is effectively no longer live and should be disposed of/garbage collected, and so it will no longer be in the update path anyway!<p>The mixed push/pull approach has only once nice property: it avoids "glitches" when updating values that have complex dependencies. The pull-based evaluation implicitly encodes the correct dependency path, but a naive push-based approach can update some nodes multiple times in non-dependency order. Thus a node can take on multiple incorrect values while a reaction is ongoing, only eventually settling on the correct value once the reaction is complete.<p>In other push-based reactive approaches, you have to explicitly schedule the updates in dependency order to avoid such glitches, so perhaps this push/pull approach was picked to keep things simple.
I took a similar approach in my Racket library, gui-easy[1,2]. Though I opted to not defer any computations. Any observable (similar to a signal from the post) update propagates to observers immediately, and there's no incrementality -- observables are just boxes whose changes you can subscribe to. Regarding the disposal problem, I used weak references and regarding the where to take observables and where to take concrete values as input question, I decided that any place an observable can go in, a concrete value can as well and it's been a convenient choice so far. For fun, here's an example[3] that builds the todo UI from the post.<p>[1]: <a href="https://docs.racket-lang.org/gui-easy/index.html" rel="nofollow">https://docs.racket-lang.org/gui-easy/index.html</a><p>[2]: <a href="https://www.youtube.com/watch?v=7uGJJmjcxzY">https://www.youtube.com/watch?v=7uGJJmjcxzY</a><p>[3]: <a href="https://github.com/Bogdanp/racket-gui-easy/blob/364e8becaafaab739c740a877cbdefed363a32b9/examples/todo.rkt">https://github.com/Bogdanp/racket-gui-easy/blob/364e8becaafa...</a>
Elm started as a FRP language and ended up giving up FRP[1] for ease of use.<p>If ease of use is targeted, signals might not be the best approach. I distinctly remember things becoming easier when they went away.<p>[1] <a href="https://elm-lang.org/news/farewell-to-frp" rel="nofollow">https://elm-lang.org/news/farewell-to-frp</a>
Topical, because Angular 16 was just released with ... Signals.<p>Used in <i>some</i> places to simplify RxJs or not need it at all. <i>Some</i>, not all.<p>They are looking towards a future where they can get rid of Zone.js and its strategry to change detection. I see this as a step along that part.<p><a href="https://blog.angular.io/angular-v16-is-here-4d7a28ec680d" rel="nofollow">https://blog.angular.io/angular-v16-is-here-4d7a28ec680d</a>
The author does a lovely job of covering a number of the interesting ideas in this space. But reactive programming is such a tough sell. I know from experience.<p>I maintain a reactive, state management library that overlaps many of the same ideas discussed in this blog post. <a href="https://github.com/yahoo/bgjs">https://github.com/yahoo/bgjs</a><p>There are two things I know to be true:<p>1. Our library does an amazing job of addressing the difficulties that come with complex, interdependent state in interactive software. We use it extensively and daily. I'm absolutely convinced it would be useful for many people.<p>2. We have completely failed to convince others to even try it, despite a decent amount of effort.<p>Giving someone a quick "here's your problem and this is how it solves it" for reactive programming still eludes me. The challenge in selling this style of programming is that it addresses complexity. How do you quickly show someone that? Give them a simple example and they will reasonably wonder why not just do it the easy way they already understand. Give them a complex example and you've lost them.<p>I've read plenty of reactive blog posts and reactive library documentation sets and they all struggle with communicating the benefits.
The previous article in the series is also a very interesting read: <a href="https://tonsky.me/blog/humble-state/" rel="nofollow">https://tonsky.me/blog/humble-state/</a>
This is what MobX does and so does Vue and a few other frameworks like Solid or Qwik (though with a different rendering model) - hardly a novel idea.<p>Heck even in lisps there was reagent which was basically this and had atoms/signals :)
Interesting that this is Clojure and it doesn't mention Hoplon/Javelin[0] as prior work. I've used Hoplon/UI[1] to implement a moderately complex web app ~6 years ago. The library is practically a prototype, pretty much dead by now. However, I found the ideas interesting.<p>I find the biggest benefit of using a fringe library like this is the ability to read and understand the whole implementation. It's really simple compared to something like React.<p>[0]: <a href="https://github.com/hoplon">https://github.com/hoplon</a><p>[1]: <a href="https://github.com/hoplon/ui">https://github.com/hoplon/ui</a>
I'm working on a project to make bootstrap work without js. Similar state management, check at
<a href="https://noojs.pages.dev/components/accordion.html" rel="nofollow">https://noojs.pages.dev/components/accordion.html</a>
<a href="https://noojs.pages.dev/components/modal.html" rel="nofollow">https://noojs.pages.dev/components/modal.html</a>
This article would be more compelling if the demo videos showed a UI that actually worked. I'm left wondering if their day job is building consent dialogs for websites.
The observable syntax is confusing. Lisp uses *earmuffs* syntax for global variables, if you only use one muff for an observable variable, how would you express a global variable that's observable? Using **lopsided muffs*?