I'm having trouble finding a good explanation for how Hoplon and Reagent/Re-frame compare. I know Hoplon uses a "spreadsheet" metaphor with Javelin and doesn't use React, and Reagent uses FRP and React, but spreadsheets are sort of FRP, aren't they? How does the metaphor diverge? I want to make an app where much of the code I could reuse for the web, my phone, and the desktop, though this will most likely be a desktop-first app via Electron. I want to make a personal knowledge base (https://en.wikipedia.org/wiki/Personal_knowledge_base), so I want to be able to query and explore a multimedia graph database rendered in canvas or WebGL (I'm not sure of the GUI side yet, but the data structures side is pretty well-defined for me). I want to have the database be immutable and versioned, so I've been looking into using DataScript as the base for my database. How would DataScript fit into Hoplon or Reagent?
Can you help me understand the pros and cons or differences between Hoplon and Reagent for someone who hasn't used React or ClojureScript before? I use JS a lot, but I don't have any real experience with the React or ClojureScript ecosystems nor even Clojure, so I don't quite know why I would want CLJS-flavored React any more than I know that I would want Javelin. I apologize for requesting such a comprehensive explanation from such ignorance. There's so much information to understand that it's difficult for a newcomer like me to make sense of it and make a good judgment on which framework/library is best for me. I have dabbled in different Lisps but haven't used any for real projects, though I've made a Lisp interpreter. I say this so you realize I'm not a complete newbie when it comes to Lisps in general, though I'm definitely a newbie to Clojure(Script).
so if you're new to clojurescript and you're not already a react expert i think you'll probably benefit from at least prototyping something in hoplon
that's great to hear! I'll definitely start with hoplon and see where that takes me, then. do you have any experience with using hoplon with datascript? how hard would interop be?
if possible, I still would like to know how the reagent/react model differs from hoplon, if only for my own intellectual curiosity
so the idea behind react is to emulate an immediate mode rendering surface on top of the DOM
so the pattern with react is appealing because you make clientside applications (applications that run in js in the client) that are organized the way you'd make a php application or something
each request results in loading new html that was generated by php program in the server
when you call it with parameters it blows away the html int he DOM and generates a new DOM from the html generated by the rendering function
but if you actually blew away the entire DOM and recreated it every time anything changed, it would be a lot of work
one of which is that you can add a callback to be called whenever the value in the mutable var changes
given the contents of the atom, it returns some representation of the html you want in the dom
so now if you update that atom, the dom is rerendered according to your render function
because just like with the stateless php server model, it's very difficult to handle mutable state in that world where everything is nice and stateless
like a framebuffer or console, yes, because you can just overwrite things sequentially, and the things themselves are stateless
some of it is even computed by the browser itself (like the width of the element, for example, which is a property of the element, but it can change at any time when the browser decisdes to adjust the layout)
and building an immediate mode thing on top of a retained mode thing is an api inversion, and that never works out well
callbacks that are called when an element is put into the dom (because you don't control that)
whenever you have an api inversion you'll end up with lots of complexity when you start using it for real
var a = document.createElement("DIV");
a.appendChild(new TextNode("hi world"));
return a;
so when the model changes, hoplon deals with that by using javelin instead of the analogous diffing
``` (page "index.html")
(def clicks (cell 0))
(html (body (button :click (fn [event] (swap! clicks inc)) (text "You clicked ~{clicks} times!")))) ```
if you pass a function as the value of an attribute it's unambiguous: you want to add a event handler
there is no other useful way to interpret function values as attributes of an element, right?
``` (page "index.html")
(def clicks (cell 0))
(html (body (button :click (fn [event] (swap! clicks inc)) :text (cell= (str "You clicked " clicks " times!"))))) ```
first, this looks kind of like a normal computer program, not some wacky special webapp
where you read input, do work, and maybe wait for more input if you're making an interactive program
so you can basically use all the normal development concepts that apply to normal computer programs
if you want to do something before some element is created, you just put the expression that does the thing above the expression that creates the element
so we developed some macros to help with that, to preserve the benefits of static allocation, but also allow for dynamically adding things at runtime
``` (def things (cell ["one" "two"])
(html (body (ul (for-tpl [thing things] (li :text thing))))) ```
there is a corresponding regular function, but the macro does some nice syntax sugaring to make it look nice
so that's like a for loop, it assigns thing
to a javelin cell that contains the value of the nth item in things
if I found myself in a similar situation, would making a macro like for-tpl to get around it be difficult?
the interesting thing is what happens if you add a new thing, or remove a thing from the things
vector
remember the for-tpl
made that thing
cell that contains the value of the nth item in things
right?
basically if you can avoid deallocating and reallocating elements, you can avoid 99% of the complexities of managing state
we did a bunch of research into frp and decided we only needed a small set of features
but since you've been listing all the benefits and cool aspects of hoplon, could you enumerate on what you don't like / hate / would like to change about it?
that's far less important to me than desktop and web, and electron ought to work just fine with hoplon since it works with clojurescript well, I imagine
perhaps you guys could prerender as an optimization at the start of an app. does that make sense?
my understanding of FRP has long been of dataflow with pure functions operating on reactive values
also it's hard for me to see the difference between a lazy formula and a regular function