hi I have a silly question: is Hoplon alive and well? I really like the philosophy behind it but I noticed that commits are quite infrequent for it and that commits for Castra stopped almost 2 years ago. I'm not assuming that a project needs to be constantly added to / improved, I'm totally ok with the idea that sometimes a product is just done and we can stop adding bells and whistles. I just want to make sure that I'm investing in a framework whose parents are still caring for it 🙂
@danieleneal would you mind sharing the reddit post?
https://www.reddit.com/r/Clojure/comments/bqh0z4/virtual_dom_is_pure_overhead/eohn35i
thank you!
@geo.ciobanu it’s definitely alive, i think it could benefit from more users… but there are users, and @flyboarder actively maintains
among frameworks i think hoplon is distinctive, as we have removed from it over time, and it has no underlying deps such as react
@alandipert ty!
removing from something is rare 🙂
I also intend to remove some more overhead that I didnt fully develop, 7.3 has been a long time coming
it’s almost ready
gotta fix the reload appending issue, which seems to be a recurring problem when we work on the element init
I have what I know is a simple question to you but quite a mystery to me. I understand how to use cell and cell= but I'm baffled by how it actually works (and not smart enough to figure out from the source code) When I have a (cell (clicks 0)) and I do 1. (def clicks-even? (cell= (even? clicks))) this works as expected. But when I do 2. (even? clicks) I get an error. In Clojure evaluating form 1 would evaluate (even? clicks) first and then everything else. However form 2 tells me that even? expects an integer. The source code uses a macro for cell= so there is some magic at play. Is there a simple way to explain what the macro does? If not possible don't worry I'll come back to this question once I learn more
Either way I'm bought into the model an committed to using Hoplon. Quite surprised more people don't use it, it's super intuitive and elegant
Working on a react native app for an organic farm, in cljs :) also just moved to Lithuania and going to be working remotely so it's a strange but exciting time
i also find that surprising! it's so easy to keep in your head, compared to the whole react ecosystem
@geo.ciobanu re: cell=
, it is a macro, and it does some code-walking to try and figure out which values are cells. when it encounters a cell, it treats it as an input parameter, such that any time the value of one of the cells within that form changes, the formula cell's value recomputes
within the context of your example, clicks
is a cell, and when you make a formula cell like (cell= (even? clicks))
, the formula cell's value updates each time the clicks
cell's value updates, and cell=
lets you express the new formula cell value in a more concise way, where the cell values are sort of "unpacked"
i think it takes a while to fully wrap your head around that idea. it took me a while, anyway. but it does become second nature after a while
(even? clicks)
by itself produces an error because clicks
isn't a number, it's a cell
you can do (even? @clicks)
to get at the value of clicks
, but in practice you will almost never dereference a cell directly like that
in my experience, any time i find myself putting an @
symbol in front of a cell, i've found that i'm doing something wrong
Aren't there some places where @
in front of cell is necessary?
Like when passing attribute value from parent to child, you have to deref it.
there are exceptions, for sure
one example is when you're implementing a :click
handler
I use
(defn event-target-node-val [evt]
(-> evt .-target .-value))
for :click
handler to get value of event.
a click handler is a function that gets run at the point in time when you click, and it's separate from the hoplon workflow of input and formula cells, so if your click handler needs to use the values of cells, you have to deref those cells
there is one benefit to cell=
in my opinion, from an abstraction point of view
i.e.:
(defn foo [x]
(cell= (+ y x)))
^^ here x
can be a cell or a regular value, either one will workthis is key in my opinion, or you end up needing to box everything
+1. i've used that trick quite a bit
if you do it right, you basically end up in a world where you don't have to think about whether things are cells or unboxed values
yep
the formula-of
is also key, of course
in some places you're making glue or plumbing code, so you know which things are cells and which arent
especially when you need an anonymous formula that no other code will ever have access to
vs. say defining a function with arguments
i like formula-of
because i sometimes find the ~
cell indicator thingy used within cell=
to be confusing, so formula-of
gives me an escape hatch when i want to be more explicit about what the inputs are to my formula
yeah totally
lol i'm an idiot, all the cell constructors can handle cells or values, i don't know why i thought it was just cell=
, sorry for the confusion
oh, i didn't know that either! i assumed it was just cell=
too
formula
and formula-of
etc. also have that property
has anyone done benchmarks of hoplon wrt react
we have a pretty large, complex application with a ton of data and many screens and it's very snappy
however there are limits to what you want to do in cells, naturally
🙂 I was just more thinking with all the recent excitement around svelte, it would be funny if hoplon had been there the whole time, quietly outperforming react...
if anything hoplon does fewer DOM updates on average, i would expect
but that's because cells do more work
yeah that would be my intuition
I haven’t used/seen formula-of but will look into it
But yes when I just need to things get done thinking about cell= as literally a calculated sheet cell makes it super easy
I initially tried to reason it as a subscriber to the cells and values it uses - but the spreadsheet model is much more universal and easy to reason about
One more question: we can do (p clicks) (Clicks is a cell defined as in the tutorial (clicks (cell 0)) ) So (p clicks) works but (p (+ 1 clicks)) does not, and we have to use a cell= instead. It's a bit intriguing to me that I can use the cell itself as a value in a p macro/function AND it gets updated properly but cannot process that value in any other way - I have to use cell= to do that. Just to be clear I love the system and I am using it easily, it's just my curious side that's intrigued. Essentially since these are macros (p and cell=) I am ok to assume they do lots of work behind the scenes and just use it as a black box, but I wanted to raise it as something that, if I understand, I'll gladly create a PR for the tutorial to clarify it for other potential newcomers with the same question.
@dave I would definitely add the x+y example to the tutorial as well it's really eye opening
Glad to create a PR for it (with thoughtful explanations around it) sometime this week
i think those would be great things to add to the tutorial
having the hoplon.core elements (`p` et al) include an "implicit cell=
" is an intriguing idea. i wonder if there would be any negative implications
can cell=
be nested? if not, that could cause problems
you don't usually want to nest them
really you never do
@geo.ciobanu when you do (p "foo")
for example, it evaluates to a DOM element equivalent to the following javascript:
document.createElement("P").appendChild(document.createTextNode("foo"))
however, when you do (p bar)
where bar
is a cell, the p
function sees that its argument is a cell and wires that cell up to update the text node whenever the cell changes
so in your case when you do (p (+ 1 bar))
you have an issue because the +
function doesn't understand how to add 1 to a cell
but (p (cell= (+ 1 bar)))
works because in that case the p
functions argument is just a cell
strings and numbers are converted into text nodes by the element functions (eg. p
, div
, etc)
you can also do (p :id "foo" "bar")
to have <p id=foo>bar</p>
or (p :id (cell= (str a "-" b)) "bar")
where the value of the id
attribute is a cell
then the attribute is updated reactively
@micha that makes sense thank you so much! I'll make sure to update the documentation asap in case others wonder the same thing in the future
đź‘Ť any time!
Yes we are probably more performant, but only since the recent 7.x releases