It's great to see Elm crediting Om for some of its ideas. The cross pollination between the Elm and Clojurescript community is great. Looking into Zelkova (https://github.com/jamesmacaulay/zelkova), an Elm style signal library for Clojure, right now. It's a great time to be a fan of stuff like this.
re-frame doesn't get enough love so here's an overview. re-frame encourages you to keep the state of your app in one map and treat it like a database. re-frame has 4 main parts:
- DB: where your global, shared state is stored. If that sounds scary and you use databases often, that's logically inconsistent. The DB is usually a map in an atom. (so it is mutable via transactions).
There are 2 ways for views to interact with the db - via dispatching handlers and subscribing to subscriptions.
- Handlers: analogous to stored procedures on the database. Handlers are pure functions that act on the database. The value returned by the handler is the new value of the DB. The handler gets registered and can be used as a high level declarative function from the views. Here's an example from our current app:
(register-handler
:cart-order-failed
(fn [db [_]]
(assoc db :cart-order-failure true)))
- Subscriptions: analogous to materialized views on the database. Allows you to watch a specific part of the state-map, do some computation, and rerun only when that specific part is updated. Here's another example:
(register-sub
:user-info
(fn [db [_]]
(reaction (->
;; never give out the password if it's there
(get @db :user)
(dissoc :password)
(dissoc :pass2)))))
So the data flows like this:
DB -> Subscription
^ |
| v
Handler <- View
The view also turns into a react.js component and is rendered to the vdom using immutable data structures, but that's Reagent not re-frame.
Sure it does, it was pretty much the only thing talked about on the cljs mailing list for about two weeks solid. It is a fantastic library though (I'm using it right now!)
Hey neat, that's similar to how Flux works, architecture wise. It's really nice in practice, and I've been looking for an excuse to play with some front end functional languages, I'm going to check it out for sure.
The benchmarks are very interesting. I wonder what React's performance would look like when using immutable data structures, such as those by Immutable.js (another FB project). It seems to me that you would again get the benefit of immutable data in the diffing algorithm; namely that the one can check if any data has changed just be checking shallow equality.
I really admire Elm for being a trailblazer for pushing techniques such as reactive programming, but it seems to be that it's unlikely to be very mainstream. This is why I'd love to see the performance benefits using more mainstream solutions with JS.
Semi-tangential note: React comes with the helpful `React.addons.update`, which implements "immutable data structures" in an extremely simple way.
I'm working on a medium-sized React application where all application state changes go through this function—there's one big state object with all substate, and we don't do any mutation inside of it. We haven't needed to benchmark anything yet, nor do we have any extreme performance requirements.
Since all our state updates work like this, we can use `PureRenderMixin` on all components, which gives us the kind of shallow equality behavior you describe.
They do implement `shouldComponentUpdate` on the todo items in a way that should give about the same performance boost. (All the pure render mixin does is implement that method using shallow equality.)
I love seeing real world consequences of pure functions. They are often praised for simplicity in development but this is a great example of leveraging constraints to build more performant solutions.
I used Elm in a personal project. It's a joy to play with but the standard library has some bugs that made it impossible for me to continue development.