Hacker News new | past | comments | ask | show | jobs | submit login
Functional Reactive Programming with Bacon.js (flowdock.com)
114 points by trevoro on Jan 22, 2013 | hide | past | favorite | 36 comments



I am not an FRP expert but I've played around with both Elm [1] and Flapjax [2]. With both libraries, I ran into a basic mismatch with what I wanted to do. They both make it very easy to have static controls create dynamic behavior. You create the controls, observe them, and then combine their signals to output whatever dynamic output the program has.

But most interesting web UIs are not static->dynamic; they instead involve dynamic and circular dependencies. Pressing the "add new todo" control doesn't just dynamically affect the display, it also creates new controls that need to get added into the set of observable things that affect the display. This idea, of modifying existing observables to include new observables, is somewhat problematic. In examples I've seen, it ends up leading back to code just as unfortunate as imperative callbacks.

If you can use Bacon to create an entry for TodoMVC [3] showing how to have dynamic->dynamic dependencies, I'll be sold.

[1] http://elm-lang.org/

[2] http://www.flapjax-lang.org/

[3] http://addyosmani.github.com/todomvc/


This is where "event switching" comes in. Unfortunately, I have not used Elm or FlapJax, so I am not sure if the terminology is the same there.

Traditional FRP has two main concepts: behaviors, which are values that can change continually, and stream of events. Scanning over this blog post, these ideas correspond roughly to Properties and EventStreams respectively in Bacon.js.

Event switching is just having an event stream that itself contains behaviors. There's a great blog post[1] about this using Reactive Banana and Haskell.

[1]: http://apfelmus.nfshost.com/blog/2012/09/03-frp-dynamic-even...

Most of the post is fairly Haskell-specific, talking about the type system, but the basic idea should be applicable here as well.

The running example is a bar tab. You want to be able to create new entries in the tab, which are just text entries that give you a price. So you would create something like

    entries :: Event [Behavior Price]
That is, you have a stream of events that contains behaviors corresponding to each text entry widget you've added. This makes calculating things like the sum of all the widgets relatively easy.

I'm not sure how other libraries support this dynamic event switching though. My understanding is that it is somewhat tricky to implement efficiently.


FWIW, Bacon.js implements switching with flatMap and flatMapLatest

Helpful diagrams: https://github.com/raimohanska/bacon.js/wiki


Have a look at pyykkis' implementation of TodoMVC using Bacon.js, Transparency and Backbone Models. I think he accomplishes just that.

https://github.com/pyykkis/todomvc/blob/bacon-transparency-r...


It looks like events from newly added controls are captured here using asEventStream with jquery's event delegation.

More about event delegation here: http://api.jquery.com/on/

$('#container').asEventStream('click', '.someclass')

If an element with someclass is ever added as a child of #container, clicks on it will fire events. This is true even if the someclass element is added after the asEventStream call.


Thanks! That one file is really instructive.


We're pragmatic about FRP and also rely heavily on Backbone. For some cases, the MVC approach seems better, for others Bacon is a better fit.

In Flowdock, there is a form that automatically validates parts of the data in JS while needs to confirm other parts with server. During server-side validation, a loading indicator is shown and success enables the submit button. Using Bacon, it has been easier to focus on the logic instead of handling state. But the logic is quickly quite hairy, indeed.

Japsu pointed out that there is a TodoMVC implementation with Bacon and Backbone, but it'd certainly be interesting to see/do a pure-FRP implementation.


I'm interested to see if using FRP principles in conjunction with Backbone makes sense. I love Backbone, but I feel like there are times I'm worrying too much about the DOM because I don't feel like abstracting out yet another subset of data into a model. If it was as quick and simple as calling a few functions (binding callbacks to existing view functions), then I feel like it would really clean up my code.


Our functional reactive web framework is specific for the R language but supports what you're describing (if I understand you correctly).

http://rstudio.github.com/shiny/tutorial/#dynamic-ui (scroll down to reactiveUI)

An example: http://glimmer.rstudio.com/winston/dynamic_ui/ https://gist.github.com/4211337


TL;DR: Reactive Programming ≈ Sequence Comprehensions + Futures.

This looks pretty similar to a .NET library called Rx (Reactive Extensions). We're using it in a MonoTouch iOS app and I found it to solve some problems in a very convenient way. If you used functional style in your code, you know it shines in mapping/filtering/aggregating/reducing sequences of data. In .NET LINQ sequences have type of IEnumerable. You can think of Rx's IObservable as of IEnumerable's odd twin brother. The main difference is you IEnumerable is “cold” by its nature: it produces new items when you ask for them by calling MoveNext(). It doesn't do anything by its own. It's also synchronous.

IObservables, however, can both be cold and hot, i.e. they can yield items without being asked to. It's like IEnumerable but with “don't call me—I'll call you” approach. Because of this, it doesn't have to be synchronous. Long processes that emit one item at a time, which may later be transformed, processed in batches, throttled, etc, benefit from being expressed via IObservable. The benefit I found is you can easily switch between different asynchronous data source implementations.

For example, it's trivial to write an IObservable wrapper around iOS Photo Library that will yield one item at a time. Then you can write a function that compares cached items in array with new items that arrive from photo library, and return IObservable of “differences” between cached and new data. Then you group those differences using built-in methods into batches—and feed them to UICollectionView so it can animate the updates as the application receives them from system API.

Then you just write another IObservable implementation for getting photos from Facebook, and wrap it in a function that will pre-fetch their thumbnails before yielding them. It is also an IObservable. You already implemented updating collection view, so you just plug in your new asynchronous data source and that's it.

Need to implement a Dropbox file picker? You already implemented collection view logic, diff logic and prefetching images, so you just need to wrap Dropbox folder fetch API in an IObservable, and merge IObservable-s from nested folders.

On top of that, you can add some caching, and magically it will work for any data source.


Yep! It's super similar because Bacon.js is a descendant:

- Microsoft creates Rx (Erik Meijer, one of the haskell developers)

- Microsoft releases RxJS, a js implementation of Rx

- Juha Paananen gets fed up with some RxJs wtfs (http://nullzzz.blogspot.com/2012/01/things-you-should-know-a...) and makes Bacon.js


I did not know that! Thanks for sharing this.


Yes, according to the author of Bacon, it is heavily inspired by the JS flavor of Rx, RxJS.


Roger that. I got into trouble with Hot and Cold Observables and wanted a model that fits my needs a bit better. Hence Reactive Bacon (https://github.com/raimohanska/reactive-bacon). Then I realised I cannot run Haskell in some of the contemporary browsers and translated it into Javascript :)


Yeah, compiling Haskell to JavaScript is tricky at the moment.

Happily, Agda has a JavaScript backend. So now you can fill your UIs with dependently typed goodness :P.


Anyone who's interested in this should also take a look at Functional Reactive Bindings: http://documentup.com/montagejs/frb/

Boasts of realtime, 2-way bindings between any JS object.


That's interesting! Do you have an idea how they implemented bindings between arbitrary JS objects? Polling?


It uses ES5 getters and setters to replace the property and react to changes. This is what makes it realtime, after the set all bound properties will have their new values.


It really disappoints me when good projects are given names that trigger bad mental associations.

Sure, everybody loves bacon – except vegans, vegetarians, Jews, and other swine-shunning cultures – but I really don't want to be thinking about bacon when I'm programming. Nor do I want to evoke the smell, taste, and unhealthiness of bacon, nor the dirtiness of pigs, in the minds of people I talk to about Bacon.

Largely for this reason I will probably not try, use, or try to get my friends to use Bacon. Please consider changing the name, perhaps to something that evokes the conceptual spirit of the project, because I'd like to see more people adopting FRP techniques.


personally, my biggest name-related gripe is ungoogleableness.

I often browse google for solutions, but I miss a lot of interesting, popular, relevant blogs when the project name is a common noun utterly unrelated to the project. I recognise naming is difficult, but it makes it hard to find popular, interesting, relevant blogs when I have to swim though the mass of web pages that use the common noun.

Sometimes I wish more projects would call themselves FRP20x14qq77aciq or something approaching uniqueness. Almost like 0x10c. At least until we get some semantic tags to say "and I mean something to do with programming and definately not anything to do with what this common noun means 99.9999% of the time".



Until someone calls it just bacon. Inevitable.


Which will then be confused with the Ruby testing library.

At least there the naming sort of makes sense. Spec sounds like Speck, which is German for bacon (sort of).


Sad to see you downvoted. Apparently responsible naming is a valid HN topic only when the library has titillating name with gender bias like upskirt [1] or pantyshot [2].

Maybe a better name would be pigfucker.js so as to more equitably offend everyone. But that's probably not necessary since I bet bacon.js was named after Francis Bacon anyway - right nullzzz? :-)

[1] http://news.ycombinator.com/item?id=2729320

[2] http://news.ycombinator.com/item?id=2748669


Choosing a name is hard if you consider coolness, pronounceableness, googleableness, politically-correctness and so on. Also at the time I was choosing a name for a hobby project, not an Enterprise Framework. Feel free to make a veggie fork :)


Good point about Francis Bacon – that didn't occur to me and, for my own uses, I might be able to drive out the mental associations by fixating on Sir Francis.


So you would never use Satan.js? And if your dad was killed by a gnu, you would only use BSD's? I hope you like apples and windows, it's a tough business if you don't...

How would you cool yourself if you didn't have sweat glands? Blaming pigs for being unhygenic is like blaming cancer patients for not having hair.


> So you would never use Satan.js?

I happen to find Satanic imagery a bit cool, so I probably wouldn't mind, but others might. Would you use a project called Vomit.js? Diarrhea.js? Ebola.js?

> And if your dad was killed by a gnu, you would only use BSD's?

Um, perhaps?

> I hope you like apples and windows

Apples and windows are relatively benign objects without disturbing imagery attached to them.

> How would you cool yourself if you didn't have sweat glands? Blaming pigs for being unhygenic is like blaming cancer patients for not having hair.

Who's blaming pigs? Pigs, their mud, and their parasites are simply unsavory to think of for many people. Likewise, bacon itself is so savory that my mouth starts watering and I can't stop thinking about salty fat. For others, bacon is either disgusting or something to be shunned.


> Apples and windows are relatively benign objects without disturbing imagery attached to them.

I think this is how most people think of bacon.


i feel the same way about Celery.


Does anyone know of anything similar to this in python? I did a quick look around but came up empty


Trellis comes to mind. There's also Twisted if you're interested in event-driven programming.


I think this is related but not sure: http://www.cs.umd.edu/projects/PL/arrowlets/


It strikes me that this would lend itself well to a graphical programming interface (a la Quartz Composer).


Have you guys seen LiveScript?


I have and I love it although it's fairly orthogonal to bacon.js. The problem with livescript is that although its absolutely beautiful to a haskeller like me, almost no one uses it so the tooling is weak and building a big project in it is a massive risk.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: