FRP with Bacon.js



FRP with Bacon.js

3 4


bacon-mloc

My Bacon.js presentation for mloc-js

On Github raimohanska / bacon-mloc

FRP with Bacon.js

Juha Paananen / Reaktor

Imperative code

List managers = new ArrayList()
for (Employee employee : employees) {
  if (employee.title.equals("manager")) {
    managers.add(e);
  }
}
return managers;
          

variables, loops, ifs, mutable data structures

FP


          employees.filter(_.title == "manager")

          

FRP

a paradigm

FP - Lists

FRP - Events

Callback hell

$.ajax("/cats").done(function(cats) {
  $.ajax("/dogs").done(function(dogs) {
    doStuffWithCatsAndDogs(cats, dogs)
  })
})
          

Imagine adding giraffes and bats

State hell

var active = true;
var timeout = null;
function setInactive() {
  active = false;
}

$(window).on('keydown mousemove', function() {
  active = true;
  clearTimeout(timeout);
  timeout = setTimeout(setInactive, 30000);
})
          

variables: 2

Bacon.js

a library

Not a framework

Not a jQuery plugin

Not an insult

~ is moar liek _

EventStream

Source of events

EventStream

Observable

EventStream

map, filter, merge, concat, flatMap

Demo

keyups, map, filter "wanna see flatMap"? later, sequentialy flatmap delay throttle

Property

time-varying value

Property

Observable

Property

map, combine, flatMap

keyUp = Event

keyState = Property

Spreadsheet

+ =

Callback hell?

Bring the whole zoo

var cats = Bacon.UI.ajax("/cats")
var dogs = Bacon.UI.ajax("/dogs")
Bacon.combineAsArray(cats, dogs)
     .onValues(doStuffWithCatsAndDogs)
          

combineTemplate

function get(name) { return Bacon.UI.ajax(name) }
var zoo = Bacon.combineTemplate({
  mammals: {
    cats: get("cats"),
    dogs: get("dogs")
  },
  fish: {
    sharks: get("sharks"),
    whales: get("whales")
  }
})          

combineTemplate

{
  mammals: {
    cats: ["Garfield", "Hercules"]
    dogs: ["Yo Dawg"]
  },
  fish: {
    sharks: ["Jaws"],
    whales: ["I'm mammal!"]
  }
}        

State hell?

Variables: 0

var activity = $(window).asEventStream('mousemove keydown')
var timeout = activity.throttle(30000)
var active = activity.awaiting(timeout)
          

Application Architecture

MVC

TodoMVC

Model

// a real one, but stripped
function TodoListModel() {
  // todoAdded :: Bus Todo
  this.todoAdded = new Bacon.Bus()
  this.todoModified = new Bacon.Bus()
  this.todoDeleted = new Bacon.Bus()
  // allTodos :: Property [Todo]
  this.allTodos
  this.activeTodos
  this.completedTodos
}
          

Model

// a real one, but stripped
function TodoListModel() {
  this.todoAdded = new Bacon.Bus()
  this.todoModified = new Bacon.Bus()
  this.todoDeleted = new Bacon.Bus()
  // changes :: EventStream ([Todo] -> [Todo])
  var changes 
  this.allTodos = changes.scan([], function(todos, f) { 
    return f(todos) 
  })
}
          

baconjs.blogspot.com

View

function NewTodoView(element, model) {
  // todoAdded :: EventStream Todo
  var todoAdded;
  model.todoAdded.plug(todoAdded);
}
          

baconjs.blogspot.com

Application

function TodoApp() {
  var model = new TodoListModel();
  var hash = Bacon.UI.hash('#/');
  new FilterView($('#filters'), hash);
  new TodoListView($('#todo-list'), model, hash);
  new NewTodoView($('#new-todo'), model);
  new ClearCompletedView($('#clear-completed'), model);
  new TodoCountView($('#todo-count'), model);
  new ToggleAllView($('#toggle-all'), model);
}
          

baconjs.blogspot.com

Recap

Future Plans

1.0

baconjs.com

bacon.UI

bacon.model

bacon.matchers

Francis

K THX BYE

Bacon.js

@raimohanska