Things like this have been done many times before. Houdini lets you create shaders with node graphs and plenty of other programs have done the same thing. It has a lot of advantages in that more constrained space.<p>The problems are always the same but I think they aren't clear until someone has already gone down this road.<p>1. Building expressions out of nodes is much less information dense that just typing them out. What would be a single line of text can end up being a lot of nodes and taking up a lot of screen space.<p>2. Expression ordering isn't as clear, since it is a graph of dependencies and to figure out what runs when you have to keep tracing dependencies backwards.<p>3. Branching is tricky for the same reason. A graph of dependencies makes branching much less clear due to order and a scrambled graph of nodes.<p>4. Loops are more difficult because they also depend on the order of execution and graphs can make that difficult to decipher and difficult to illustrate.<p>5. State becomes difficult because you need ordering and it depends on external dependencies.<p>A lot of graph problems can be seen in haskell too. You have something that works very well when what you are doing is all a series of transformations, but there are large chunks of programming that don't fit in to this model.
I'm impressed with the declarative programming model (aka reactive programming), and the ability to compose new blocks/visual components as a result.<p>It feels like we're finally starting to overcome all that we lost in the decades since VB6/Delphi for Windows.
The problems spoke for themselves over the course of the presentation.
Something as simple as a counter was very complicated to look at, filling the screen with jiggling nodes. The presenter then introduces a bug while trying to decrement, and is unable to debug it.
Interesting, and clearly a lot of work's gone into this (60,000 lines of Typescript), particularly the UI, which is impressive (if, sometimes, over the top). I've been developing a similar system (<a href="http://www.fmjlang.co.uk/fmj/tutorials/TOC.html" rel="nofollow noreferrer">http://www.fmjlang.co.uk/fmj/tutorials/TOC.html</a>) and it's interesting to note the similarities and differences.<p>Similarities: code as directed graphs (less obvious in FMJ); can only connect outputs to units of compatible type; if and wait (looping is handled differently); sticky values; sliders. These design decisions are practically forced on you, but are often absent in earlier visual dataflow languages (e.g. Prograph, LabVIEW).<p>Differences: (1) inputs are named in Unit, ordered in FMJ (though they're named in formulas and edges can be labelled). (2) I experimented with automatic code layout but found this was too slow and not always what I wanted. Well done for getting this to work. (3) FMJ is now fully homoiconic - this maybe isn't a priority for Unit.<p>The Unit design philosophy is explained in <a href="https://github.com/samuelmtimbo/unit/blob/main/src/docs/concept/README.md">https://github.com/samuelmtimbo/unit/blob/main/src/docs/conc...</a> . This doesn't mention earlier approaches (e.g. the Manchester Dataflow Computer, Prograph) and it seems to be based on vaguely similar ideas developed more recently (Morrison's Flow Based programming; possibly React and similar systems for web development - I'm unfamiliar with these).<p>I have a number of questions:<p>(1) How does the type system work? Is it Dependently typed, Hindley-Milner, or something more basic? (FMJ is Hindley-Milner, with dependent typing partially implemented). How are new types be defined?<p>(2) How is the visual representation stored? One criticism I faced was that people wanted a readable textual representation which would work well with existing version control systems, a problem I have now largely solved.<p>(3) How are runtime errors handled?<p>(4) Is recursion supported? (I assume yes, but I didn't see any examples.) What about macros?<p>(5) What does Unit compile to? (FMJ has an experimental compiler where programs are compiled by running their source without evaluating their inputs, output is Lisp.)
This is so eerily similar to a concept I've been thinking about for years. I want to base it off equations not functions though. Bidirectional value propagation. Figuring out how to make that work always stumped me.
Thanks for sharing. Definitely interesting!<p>I have a number of thoughts on this area.<p>* We need Graph paging: Nodal editors have too much data to present for large systems. Navigating/panning/scrolling a large screen of data is painful. I started writing a C parser (completely incomplete) with the desire to render simple diagrams for the Postgres codebase. But you know that the diagram would be too large to present every method and its relationship, so you need to paginate the graph. I was thinking of paging each method at a time.<p>* We can render graphs that are incomplete and additive, we can render a grid of graphs like tiles each all live and interactable separate graphs but also subsets of the available data. It's okay to present the same node again, with different children or connections.<p>* I've been playing around with what I call "movement programming" which is the idea we step through state of memory step-by-step and grab data to be fed into operators or functions, this generates the instruction (inferred) and the next state is displayed. The goal is that btrees and quicksort could be implemented with point and click. We visualise context on the screen at all times, which are local variables and contextual data.
Finally something that allows to have a personal repository again (after version control just stole that word). And not in Squeak. Amazing work.<p>(Does it support version control...?)
This is awesome! I have been working on a similar tool. My focus has been keeping as much as possible in a single binary (benefits of using go) so that local development and deployment to production is super easy. It can orchestrate different grpc methods together which is pretty neat. I have been digging using the Protobuf type system to express the data transfer between nodes.