freactive vs rum

886 views
Skip to first unread message

Kurt Sys

unread,
Apr 14, 2015, 9:19:09 AM4/14/15
to clojur...@googlegroups.com
Of the many clojurescript libraries/frameworks out there, both rum and freactive appeal to me the most. I tested them both only very briefly so far. Both have a target of 'the summer' to have some kind of stable 1.x release (if I'm not mistaken).

I'm wondering, is there anyone who used both of them for real applications? What would be considered strength/weaknesses of both? (And well, now I've used the words, opportunities and thread :p?) A very opinionated question, it is, but still, any thoughts, ideas or peferably experiences are valuable (at least, to me).

Alan Moore

unread,
Apr 14, 2015, 11:24:42 AM4/14/15
to clojur...@googlegroups.com
I tried them both and they are equally viable for most projects. In my case I was looking for the thinnest possible wrapper to React - and I don't use *any* of the ratom or other state tracking features so my use requirements are a bit out of the mainstream. I just needed a view layer.

I ended up with Rum for this reason but it was very much a toss up. I found I could understand the code base slightly better and liked the simplicity of the mixin support. I also found an example of integrating Datascript with Rum (same author) that was helpful because I had to integrate a similar data engine.

Freactive might be a better choice if you have a lot of animations - I seem to remember that it has explicit support for it... TBD. Let us know how you get on with whatever you choose.

Good luck.

Kurt Sys

unread,
Apr 14, 2015, 11:36:36 AM4/14/15
to clojur...@googlegroups.com
Any reason why you wanted to have a wrapper to React? freactive doesn't seem to be a wrapper, although functionality might be similar.

Anyway, thx - I'm thinking of using them both for a real (but small) for-fun project. Might be the only way find out :). I'll keep in touch.


Op dinsdag 14 april 2015 17:24:42 UTC+2 schreef Alan Moore:

Kurt Sys

unread,
Apr 18, 2015, 6:56:52 AM4/18/15
to clojur...@googlegroups.com
Op dinsdag 14 april 2015 17:24:42 UTC+2 schreef Alan Moore:
I found myself (re)writing all kinds of atoms and/or cursors to make it work in freactive - since not everything is an atom, e.g. datascript queries and websockets. Instead, I started creating just plain vanilla stuff, and got to the point where things like react components where pretty interesting, so I ended up using rum :p. I very much like the idea of the datascript chat example (http://tonsky.me/blog/datascript-chat/) application. freactive did'nt make that easy on me. rum mixins rather do...

Alan Moore

unread,
Apr 18, 2015, 1:20:14 PM4/18/15
to clojur...@googlegroups.com
Sorry for the delayed response. Yes, I stand corrected, I evaluated just about every front end library there is for ClojureScript and some of the names are starting to get confusing to my age addled brain (react, reagent, freactive, re-frame, etc..)

I really just want the DOM diffing from React and don't need any of the other stuff. I'm considering making a ClojureScript wrapper for:


My goal is to write most of the front end logic using rules (Clara is the best candidate ATM) so the view portion needs to be as simple as possible for the rules to manipulate the DOM. The rule engine provides all the data reactivity I need - any data (normal clojure data) you put into it is automatically pattern matched against the rules, including unification/relationships with existing data - as defined by your rules. Here is the general idea:

Model: Data inserted into the rule engine's working memory
View: DOM/React/Rum/vdom
Controller: Rules in the engine

It is reactive in the sense that inserting data/facts/events (from server or user/view events) into the engine triggers rules to fire, those rules may then update the UI or the server, rinse and repeat. There is no "polling the data" for changes because the engine maintains a data structure (a Rete graph) that pattern matches against your data as you insert it, edge-triggered as it were... You can query the data stored in the engine using a defquery... which is like a defrule without a RHS.

The goal for my app is to keep all the core app logic in the rules which makes them easily unit tested because the primary externalities are just data. Think of it as a reactive version of Datascript, at least that is how I see it. Also, in theory, Clara artifacts such as rulesets and sessions can be moved around a system as self contained units of logic giving you a lot of flexibility in how you organize (or re-organize) your architecture. According to Ryan Brush, the author of Clara, they deploy Clara in Hadoop jobs to great effect.

Along the same lines, another experiment I want to look into is extending the core Clojure data protocols (ISeq, Iterable, etc.) to the Clara sessions so that, to the rest of the system, the session looks just like a regular Clojure data container... or something like that (e.g. conj == insert, etc.)

I'm curious to hear how Rum works out for you. I think Rum and Quiescent are both excellent minimalist React wrappers. Om is awesome but is more than I need. If my experiments don't work out I may go back to it... TBD. If you like Datascript and Quiescent then you might want to check out:


It is a really cool app template to get you started.

I'll let you know how it goes, my app is still very much a work in progress. I'm currently working on converting the Clara codebase from crossovers to using reader conditionals so that is a bit of a diversion from the UI side of things.

As with your project, this is one of many side projects for me. I need the day job to pay the bills... :-/

Take care.

Alan



--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/kCdOQzPNAug/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.



--
-- 
"Whatever you can do, or dream you can do, begin it. Boldness has genius, power, and magic in it. Begin it now." - Goethe

Julien Eluard

unread,
Apr 18, 2015, 2:25:00 PM4/18/15
to clojur...@googlegroups.com
Hi Alan,

you might be interested by the latest release of the hipo [1] library which provides reconciliation (à la react) [2] of live DOM nodes. It is essentially a native ClojureScript 'virtual-dom' implementation using hiccup vectors as syntax.

Cheers,
Julien

[1] https://github.com/jeluard/hipo
[2] https://github.com/jeluard/hipo#reconciliation

Alan Moore

unread,
Apr 18, 2015, 2:52:35 PM4/18/15
to clojur...@googlegroups.com
Absolutely, thank you! More time to work on other stuff, yay :-)

Native ClojureScript FTW! Wrappers are convenient and good if you need to play nice with existing frameworks (looking at you React) but otherwise they seem suboptimal.

Thanks for the library Julien and a hat tip to Prismatic for dommy.

Alan

-- 
"Whatever you can do, or dream you can do, begin it. Boldness has genius, power, and magic in it. Begin it now." - Goethe

Marc Fawzi

unread,
Apr 19, 2015, 10:57:06 AM4/19/15
to clojur...@googlegroups.com
I agree starting with something basic and simple offers more learning potential.

We're actually expanding the focus of our SF Reagent Meetup to be Reactive ClojureScript with heavy focus still on the more accessible Reagent/Re-frame tools, while also bringing in one other Reactive ClojureScript framework to talk about at each meetup. I'm inclined to go with Julien's work for our first exploration.





You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.

Julien Eluard

unread,
Apr 19, 2015, 1:31:37 PM4/19/15
to clojur...@googlegroups.com
Nice! Let me know if I can help.
Also keep in mind hipo is lower level than those libraries. In particular there is nothing reactive and the reconciliation call must be managed manually.

Cheers,
Julien

Marc Fawzi

unread,
Apr 19, 2015, 2:43:13 PM4/19/15
to clojur...@googlegroups.com

Hi Julien,

Thats exactly what i had imagined!

I'm interested in the building blocks for learning purposes. Could we adapt or directly use somethjng like the reflex project https://github.com/lynaghk/reflex with hipo to demonstrate basic reactive principles?

By the way, i will email you to coordinate for our next meetup. We are going to dig into Cursive (!) and a more detailed talk on the reusable Reagent (ones that i presented) and Re-frame components (at least a discussion of them around reuse) then dedicate the rest of the meetup to discussing the design of a basic reactive framework made of low level components like hipo and reflex. Or something like that. This is all tentative.

So i will email you directly.

Thanks :)

Sent from my iPhone

Kurt Sys

unread,
Apr 20, 2015, 4:45:17 PM4/20/15
to clojur...@googlegroups.com
The basic stuff I need is really very similar. What I like about react, is not the dom diffing as such, the 'should-update' mixin. This really can make things way easier. It doesn't play as nice as I thought it to be between rum and datascript queries, but it'll work. Datascript queries are really amazingly powerful to me. I use them really a lot, and full dom diffing might be pretty, or more, expensive compared to a 'should-update'.

That said, I had been looking to clara before (for another kind of project), but I pretty much like the idea of using it as 'database/query engine'-someting. Would you implement something like the should-update on component basis as well. I'm really very interested in your wrapper/library and how it would work out.

Thx...





Op zaterdag 18 april 2015 19:20:14 UTC+2 schreef Alan Moore:

Kurt Sys

unread,
Apr 20, 2015, 4:49:29 PM4/20/15
to clojur...@googlegroups.com
Lower level means more possibilities, I suppose :).
Very interesting stuff going on.


Op zondag 19 april 2015 19:31:37 UTC+2 schreef Julien Eluard:

Alan Moore

unread,
Apr 20, 2015, 5:56:56 PM4/20/15
to clojur...@googlegroups.com
On Mon, Apr 20, 2015 at 1:45 PM, Kurt Sys <kurt...@gmail.com> wrote:
The basic stuff I need is really very similar. What I like about react, is not the dom diffing as such, the 'should-update' mixin. This really can make things way easier. It doesn't play as nice as I thought it to be between rum and datascript queries, but it'll work. Datascript queries are really amazingly powerful to me. I use them really a lot, and full dom diffing might be pretty, or more, expensive compared to a 'should-update'.

That said, I had been looking to clara before (for another kind of project), but I pretty much like the idea of using it as 'database/query engine'-someting. Would you implement something like the should-update on component basis as well. I'm really very interested in your wrapper/library and how it would work out.

The nice thing about Clara (and rule engines in general) is that you can declare that certain functions (RHS) are to be called when a set of conditions/queries (LHS) over your data evaluate truthfully. There is no need for "should-update" polling, it is more don't call us, we will call you - control is inverted. When a user or server event happens the handler code inserts the event data into the engine and then calls the fire-rules function to trigger subsequent actions based on the rule conditions.

Clara does truth maintenance which is an awesome feature but in my use case I have to work around it slightly to accommodate transient facts/events. Not a big deal just something to keep in mind when first understanding how it works.

I don't really see there being a need for a wrapper around Clara - you can use it as-is. I'm just trying to figure out the best way to integrate it in the client-side context. It was built with a particular set of use cases in mind that don't always match up with my experience with other rule engines that are more "mutation" oriented. Clara's rule engine is a value in the same way that Datomic's database is a value. This is super powerful but that means you need to organize your code slightly to take this into account.

Alan

Marc Fawzi

unread,
Apr 20, 2015, 6:35:32 PM4/20/15
to clojur...@googlegroups.com
Thank you for sharing this Alan!  Its really interesting. 

Would Clara then work with something like Hipo? I like the distinction you make between it and mutation based reactions. Very interesting topic that deserves more discussion imo.

Sent from my iPhone
--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.

Alan Moore

unread,
Apr 20, 2015, 7:07:53 PM4/20/15
to clojur...@googlegroups.com
Caution, my comments should be taken with a grain of salt. I've build prototypes with Clara in the browser but nothing of production quality. Therein could lay dragons... YMWV.

Ryan, Clara's author, uses it much more extensively on servers and such. His use cases are primarily JVM based but I hear it does quite well there.

Alan

-- 
"Whatever you can do, or dream you can do, begin it. Boldness has genius, power, and magic in it. Begin it now." - Goethe
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/kCdOQzPNAug/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.

Kurt Sys

unread,
Apr 21, 2015, 4:24:55 AM4/21/15
to clojur...@googlegroups.com
Just to be sure I get it right... What I do now, with datascript is also 'one way': all events are put on an core/async channel (well, publisher, actually). The subscribers change datascript-values. Any changes in the database trigger an update of the view:

(defonce init (fn []
(ds/listen! conn (fn [tx-report]
(rum/request-render root)))))

That's where should-update comes in handy: I don't have to keep track of all components that have to be updated by changing one value: I let the components decide themselves. It's pretty easy when reading datascript db values, but I'm still figuring out how to do it with datascript queries.


Now, with the rules engine, it would be pretty similar (well, at least, according to my mind :p): alle events are published and a subscriber adds the facts to the rules engine. A fire-rules function would be something similar to my 'trigger an update of the view'. The subsequent actions are basically 'update component'-actions? Meaning I'd write something like, for each component:

(def component ...) ; possibly using hippo-style-something?

(defrule component-rule
[query result changed] ; this would look like 'should-update'
=>
(update component)) ; and do other stuff, e.g. add 'fact' to undo-list

(... which might be put in a function/macro)


D'you have any (very) basic examples? I feel like experimenting a little with it :). I don't see the 'query result changed'-function yet, but I'm lacking some clara knowledge so far... It'll probably be something with storing the components previous state. Well, time get down to it.


Cool stuff! qsys


Op maandag 20 april 2015 23:56:56 UTC+2 schreef Alan Moore:

Julien Eluard

unread,
Apr 21, 2015, 8:28:40 AM4/21/15
to clojur...@googlegroups.com
I am also curious about the advantages of using something like Clara versus DataScript listen feature. Especially there has been discussions [1] of improving listen so that it can accept a query details argument.
Alan I can see you commented on this ticket how do you think it compares to Clara?

Cheers,
Julien

[1] https://github.com/tonsky/datascript/pull/12

Alan Moore

unread,
Apr 22, 2015, 2:11:33 AM4/22/15
to clojur...@googlegroups.com
Sorry for the delayed response - I was out of town visiting a doctor and wishing I was at ClojureWest.

Yes, exactly. That is the basic idea, data and events flow into the "session" and after each update you fire the rules, which is a kind of polling depending on how you look at it. It is more like a small loop that fires rules until there aren't any that qualify (on the agenda, as it were.) If no rules matched, nothing happens.

If you just want to see Clara in action in the browser you can look at clara's example project:

https://github.com/rbrush/clara-examples

The examples are fairly short and don't show you how to organize everything - the session is built, data is inserted, rules are fired, dom is updated all in one function. It all works but isn't how you'd set things up for an app. That is what I've been working on with the various libraries like reagent, om, quiescent, rum, etc. I will post an example shortly, it is on my other system.

Also, Clara itself has some unit tests for basic features so you can take a look at those.

My biggest hang up at the moment is the truth maintenance. I talked to Ryan and he suggested using accumulators to model transient events/data (such as browser/user events.) The problem is that if you retract data any other facts that were inserted as a result of rules firing also get automatically retracted (the truth basis is transitive for the related facts.) So that is what I'm working on - trying the accumulator approach.

Other rule engines that I've used didn't do truth maintenance, which if you need it is a super powerful feature. I suppose I'm mis-using Clara in this way but it worked great using Jess (a super nice Java based rule engine.)

Anyway, I'm sure there is a way to make Clara work. If not there is another engine posted to this mailing list that I've intended to take a look at. It doesn't take the as-a-value approach and is mutation oriented like Jess and CLIPS. I really want to see if I can get Clara to work because I like the elegance of the value approach... TBD.

Alan Moore

unread,
Apr 22, 2015, 2:47:04 AM4/22/15
to clojur...@googlegroups.com
The two are very close in concept but I think, under some conditions, Clara has an advantage in being based on the Rete algorithm. My guess is that the Rete algorithm might be more efficient but am unsure where the cost/benefit cross over is re: # rules, amount of data, etc.. It heavily depends on how much commonality/overlap and sharing happens in the graph which is dependent on your rules and their structure. Caveat emptor.

Rete doesn't have to recompute the results of the query over and over again as data arrive like I suspect Datascript would have to. With Datascript, after each query is run there is no memory of what the previous results were. Rete maintains the state of all of your rules/queries across all of your data that you insert/remove in/out it.

Re: Datascript and listen! At a conference a couple years ago I asked Rich a similar question re: Datomic, I couldn't hear his response very well but I think he said that Datomic doesn't support persistent queries and probably won't. I would think that datalog could handle it but I don't know how you'd do it. I think that pull request says the same thing basically if I'm reading it right.

I know this kind of thing is very powerfule - I embedded Jess into IE 4 as a Windows Scripting Engine way back in the day. Just like javascript, Jess code could be embedded in your page using <script language="jess">(defrule xyz ...) </script> and you had full access to the DOM and events, with all the event wiring/registration happening automagically, etc. It made for a really elegant programming model.

It worked great but internally it was a tangled mess of C++ COM objects, jscript, and java. IE 5 broke everything so I gave up on it.

As previously mentioned, I'll post a more complete example of Clara tomorrow after I recover from my trip.

Take care.

Kurt Sys

unread,
Apr 22, 2015, 3:16:22 AM4/22/15
to clojur...@googlegroups.com
They are very similar, indeed. It's true that using Datascript, queries should be recomputed, unless you save them as a kind of component state - that's what I do now: I save, well, actually rum saves, the previous result of the query and compares it with the new result (in the 'should-update' function). Basically, this logic is now embedded in a rum mixin. It would be somewhat 'more decoupled' using a state machine; state management is probably conceptually simpler. Using a state machine feels (slightly) more decomplected to me.

Looking forward to more complete examples, so I might try it out on a small test application I'm building, to get a hang of rum/datascript. I've put freactive on hold for now :).

I'm really interested in both, not only in terms of efficiency and performance.


Have fun!
qsys
Reply all
Reply to author
Forward
0 new messages