Almost a year ago I started using React for “greenfield” internal projects at work. One of the huge benefits of the web is everyone brings patterns and libraries from other programming language into JavaScript. FRP is one of these libraries to recently be ported to JavaScript. After trying a couple Flux implementations for React I was attracted to FRP (Functional Reactive Programming) libraries like RxJS and Bacon. I spent 4 months learning and building an internal app with FRP and React.

FRP tries to solve the problem of asynchronous work, event propagation and data transforms that happen as a result of events about your code base. Basically you create an observable that reacts when an event is triggered. The trigger could be a UI event, like on click, or a network request or other things. Each trigger returns a stream that you can chain (ala jQuery) to change or combine other streams together. ReactiveX group does a much better job explaining what they do. Their site is really great at explaining FRP http://reactivex.io/.

RxJS and FRP in its prime

RxJS does a lot of things really great. It allows you to create custom event streams that can have multiple listeners on the output. The observables model and chaining transforms are very useful and help keep related pieces of code together. Observables create stream that can be combined with other streams. It takes away the global events and keeps them localized to where your code needs the to react to the events. If you’ve used Mutation Observers or data binding or Backbone events in JS or KVO or NSNotificationCenter in Objective-C, RxJS like that but much more powerful. RxJS elevates data flow to be a first class architectural pattern on the level of MVC.

RxJS elevates data flow to be a first class architectural pattern on the level of MVC.

Barriers

So why did I move on from FRP? I spent 4 months with 8 hours a day of coding with FRP. I’m no expert but I hit some limitations that caused me to look to see what else was out there. It might just be that I have just not used FRP “properly” and I would love to understand it better.

In my app I had streams for network requests that transform server responses to a structure that was more useful for the UI. There were also observers on UI events. FRP has a very unique API that takes a bit to learn, even if you’ve done map/reduces before. The DSL being very unique made it harder to reuse other functions in my code base. I couldn’t reuse code but the Observable and Streams could be pasted around to leverage in other classes.

Merging and combining streams is where it got muddy really fast. I had events going that were hard to track down. I lost the finer grain control when more than one stream was being used. I’m fully aware this could be my misunderstanding about how to use FRP. At the same time, the methods a library exposes guide developers about to best use them. Take for instance Backbone’s vs. Angular’s API. Backbone is every open and easy to do things outside the “intended” use; when in Angular doing things outside the intended patterns are much more difficult. API design guide developers into certain patterns.

In the end, it was harder to reason about everything going on. Debugging FRP processes was stepping through a lot of the internals of the libraries to find where events got twisted. Using FRP in smaller more isolated uses and limiting combining streams was much more beneficial and the file size increase if you’re just using it in place of a single callback function is not very useful. FRP hits the middle ground between these very well for me.

A simpler async and data flow

So looking around and talking to friends I looked into Go lang. It has been getting a lot of press lately for good concurrency, parallelism with and without threads (for good reason). They use a pattern called CSP. You create a channel object that lets data move across it. This is very similar to FRP. Then when you want to push data on the channel or take data out, you just tell it to set the data to a variable and “park” until that data is set. So code that looks like normal is synchronous and walks line by line acutally parks and waits until something comes across the channel before going to the next line. JavaScript will be getting this with `await` in ES2016.

Go lang and CSP is really cool, right? Async work looks like sync work and all the code is together making it easy to rationalize about. But I can’t use that in my web app. That’s where ClojureScript comes in. Their community is known for just using great ideas from other programming languages. ClojureScript’s core.async is fabulous. They basically stole the best parts of Go and FRP but with an API that’s super simple. Core.async feels like programming 5 years in the future. Core async has Go channel, that “park” to make async code look like sync code and on top of that they’ve added transducers. Transducers are these awesome things to take a bunch of abstract functions that do minor task and quickly compose them together and attach them to a channel.

[ClojureScript’s] core.async feels like programming 5 years in the future.

Breaking down ClojureScript

ClojureScript’s Transducers replaced FRP’s the multiple flatMap and take functions. Transducers are just stupid little functions that can be reused in regular map/reduce/filter operations. In contrast to FRP functions used inside streams needed to understand they were in a stream. Functions used in a transducer don’t know they’re in a transducer. Basically I can reuse them with all my current map/reduce/filtering code inside async channel.

ClojureScript’s analogous structure to FRP Observables are Atoms and Atom watchers. In ClojureScript all the data is immutable. When you first hear that is sounds insane but watch Rich Hickey’s Simple made Easy and you’ll see how awesome it is to have immutable data the default option. Atoms are ClojureScript’s mutable data. Using watchers, you can have a single callback function or channel trigger when a piece of data changes.

The last pattern that we heavily use is ClojureScript version of classes. ClojureScript is a functional programming language but they’ve seen the value that OOP languages provide. When it comes to encapsulating dependancies OOP classes are very useful. ClojureScript handles this with Stuart Sierra’s Component library. It really helps control a lot of dependancies in our data flow.

ClojureScript is the Triforce of Prower

I’ve been programming in ClojureScript for the last 6 months. Do I recommend JavaScript developers to use ClojureScript? [N̶o̶] Yes (see how we use cljs & js together at Capital One). To be fair it’s really hard compared to learning another OO language. The learning curve is steep. For the first month I constantly felt like I was on a trip to Japan where I couldn’t read or written or speak and had to rely on grunting and pointing. Debugging core.async code specifically can be rough in Chrome Dev Tools. But for any challenges, learning ClojureScript is the most rewarding thing I’ve learned in the last 10 years.

In the 3 weeks it took to build our ClojureScript app I have never learned much, grew so much as a developer and understood why my OO code had bugs and how to control them. Writing ClojureScript, learning the syntax, patterns, paradigms and ideas from the ClojureScript community has been invaluable. If you’re just using ClojureScript-inspired patterns in another language, there are huge concepts you’ll miss out on. Functional programming is the future (If you look closely in The Martian, their spaceship is coded in a LISP).

http://twitter.com/puppybits

ClojureScript’s Prowess is transparent bridging to other languages

There are tons of great UI developers that can build great work with React and JS. 85% of our development time for our web app at Capital One is building UI. We don’t need a huge barrier for entry to get great developers doing great work in our web app. With ClojureScript they don’t even need to know they are using ClojureScript.

Inside of ClojureScript we use core.async, go channels, transducers, immutable data, components, atoms and atom-watchers. We can take full use of the prowess of ClojureScript. When we want to talk to the JS world we have one single file called export. It puts a JS interface on top everything. When you’re in the JS world you call a function that returns a promise that give you mutable JSON objects. This is our entire code to transform CLJS patterns to JS patterns and allow for interop.

ClojureScript runs in the browser (and Node) for our front-end web app. We’ve done some tests with wrapping it in JSCore. We can build the data synchronization, caching and business logic once and use it to power our React web app (in Node and the browser), expose a Swift/Objective-C interface for our iOS app and possibly even take it to Android. Since our server is in Clojure, we can even take parts of it’s code base and include it in the front-end clients with almost no work. I’m the only front-end developer that needs to know ClojureScript when the rest of the devs just use JavaScript.

ClojureScript is well worth it for anyone who wants learn. The community is great. The patterns I’ve learned give me a deeper understanding about alternate ways to write code. I have less bugs, less refactors and easier refactors of code. Our ClojureScript library has been pretty flawless with only a couple bugs in production. React has had an order of magnitude less bugs compared to my time doing Backbone and iOS apps. ClojureScript had a order of magnitude less bugs than React.