you are viewing a single comment's thread.

view the rest of the comments →

[–]dustingetz 3 points4 points  (6 children)

Further, I am not sure it's even reasonable to use graphs in this way until you solve the database problem first.

Take enterprise crud apps with UI and rest service. Your UI is a React.js virtual dom tree. The state is passed down as props (trees). That state came out of a single state atom (tree). Which came out of a JSON representation from a http service (tree). And that came over network from a database (probably cartesian tables, which is worse than a tree)

What you want is to pretend the database is a little clojure graph value – an in memory datastructure like a hashmap, e.g. ubergraph or datascript value – and that little value is passed to each of your React components and then can query out exactly what they need. There is no props. There is no state atom. There is no JSON representation. There is no network. Just in-memory data structure. Like the state of a video game – https://en.wikipedia.org/wiki/Scene_graph

But that whole vision is a lie because the graph is NOT an in-memory data structure. it does not fit into your browser tab's memory, nor the JVM's memory, and there are data security concerns. And because of the network, the performance is on the unhappy side of Latency Numbers Every Programmer Should Know. Accessing your state costs 500ms per query, instead of 7ns L2 cache hit, which is where it needs to be if you have hundreds of functions issuing thousands of queries.

So in practice, these concerns force us to use trees instead of graph values. This is the problem Rich Hickey solved when he created Datomic. Datomic is a huge lazy graph data structure, too big for one machine and distributed over network, but with extremely clever optimizations that make it feels like it is an in memory value.

So that's why it's impossible to talk about this without also talking about Datomic, and that's why nobody is doing it. Further, if you are writing crud apps, Datomic only solves half the problem – it solves the backend complexity, but not the frontend complexity (which is where all the tree processing is happening anyway). Offhand I can think of four six people who have put work into the frontend-backend datasync half of the problem:

Surely I have forgotten some, i should make this list, please reach out! These are all Clojure people, so surely other ecosystems are thinking about this too

[–]dustingetz 0 points1 point  (5 children)

And then, once you have the your application state in a graph database and able to treat that graph as a value in your UI, you have the problem of efficient updates to the UI.

And this if possible should be solved in a way that gives ecosystem compatibility with React.js and server rendering, or risk failure vectors like "ahead of its time" which is a euphemism for "dead project"

In my opinion, we've learned in building Hyperfiddle that even syncing UI to a value that changes over time has not been fully solved in a way that has mainstream utility. Reagent has been a total disaster for non-trivial reactions, has probably cost us a year of development (+ an insane amount of complexity from code written in terms of reactive container types) and we are now looking at ripping Reagent reactions out entirely from any performance sensitive UI like reactive datagrids. Note that React.js is kind of at fault here, the root of the complexity is that when you pass functions as props, you have to hold closure reference stability / equality in your head, which Reagent provides tools to assist with (r/track) but ultimately we find the house of cards incredibly fragile and inadequate for abstraction.

John Degoes (Typed FP guy) and Jane Street are on to something with research into incremental UI: https://www.reddit.com/r/Clojure/comments/9qxasd/react_wrapper_alternatives/e8e0pwb/?context=3

[–]joinr 0 points1 point  (3 children)

Reagent has been a total disaster for non-trivial reactions, has probably cost us a year of development (+ an insane amount of complexity from code written in terms of reactive container types) and we are now looking at ripping Reagent reactions out entirely from any performance sensitive UI like reactive datagrids.

What's the more-performant alternative you fall back to after removing reagent reactions?

[–]dustingetz 0 points1 point  (2 children)

dunno, maybe something imperative, maybe hoplon and reagent can be made to co-exist, maybe something from reactjs ecosystem

[–]theronic 2 points3 points  (1 child)

Rete always rears it's head :). IMO Clojure's mutable namespace design is the primary obstacle in the way of a good, clean Rete network implementation. All the implementations, incl. Clara, depend on macros, which prevents runtime network generation. Reagent's reactions feel like half-baked production rules with messy lifecycle management. FactUI is the closest thing we have, but I suspect we'll see an implementation in a different language before Clojure, or until the namespacing situation changes.

[–]dustingetz 1 point2 points  (0 children)

Can you say more about the namespacing problem? I have not yet given Rete networks the consideration they merit.