Functional Reactive Programming with Bacon.js

Functional Reactive Programming with Bacon.js

Introduction to functional reactive programming concepts via JavaScript and Bacon.js. Presented at JavaScript Latvia. http://www.meetup.com/JavaScript-Latvia/events/159138222/

Dd07eec06b2a1e40965605d3f32acc34?s=128

Dimitry Solovyov

January 14, 2014
Tweet

Transcript

  1. Dimitry Solovyov @dimituri Functional Reactive Programming with Bacon.js

  2. Imperative Functional x = x + 1 f(x) = …

    f(x + 1) …
  3. None
  4. ♥×3

  5. None
  6. t val

  7. Input Disk Network Timers Client-side programming is all about time-varying

    values
  8. (30,30) (50,40) (80,50)

  9. pub/sub Observer $.Deferred Excel cell …

  10. JavaScript https://github.com/baconjs/bacon.js Elm (Haskell-like) http://elm-lang.org ClojureScript https://github.com/tailrecursion/javelin

  11. None
  12. map

  13. 1 2 3 4 5 2 4 6 8 10

    x  =>  x  *  2 map
  14. filter* * I didn’t find a good picture for “filter”,

    sorry.
 However, here is my cat.
  15. 1 2 3 4 5 2 4 x  =>  (x

     %  2  ==  0) filter × × ×
  16. Mouse move var  area  =  $('#area');   var  moveS  =

     area.asEventStream('mousemove');
  17. Mouse move Coordinates map var  area  =  $('#area');   var

     coords  =  area.asEventStream('mousemove')      .map(function(e)  {          return  [e.offsetX,  e.offsetY];      });
  18. Mouse move Coordinates In hitbox map filter var  area  =

     $('#area');   var  inHitbox  =  area.asEventStream('mousemove')      .map(function(e)  {          return  [e.offsetX,  e.offsetY];      }).filter(function(coords)  {          return  hitbox.contains(coords);      });
  19. Mouse click Mouse move var  area  =  $('#area');   var

     moveS  =  area.asEventStream('mousemove');   var  clickS  =  area.asEventStream('click');
  20. Mouse click Mouse move Click info sampledBy var  area  =

     $('#area');   var  moveS  =  area.asEventStream('mousemove');   var  clickS  =  area.asEventStream('click');   var  clickInfo  =  moveS.toProperty()      .sampledBy(clickS,  function(moveE,  clickE)  {          return  [moveE.offsetX,  moveE.offsetY];      });
  21. Element text Mouse click Mouse move Click info sampledBy onValue

    var  area  =  $('#area');   var  moveS  =  area.asEventStream('mousemove');   var  clickS  =  area.asEventStream('click');   moveS.toProperty()      .sampledBy(clickS,  function(moveE,  clickE)  {          return  [moveE.offsetX,  moveE.offsetY];      }).onValue(area,  'text');
  22. fold

  23. 1 2 3 4 5 2 4 7 11 16

    (a,  x)  =>  {  a  +  x  } fold 1 a =
  24. Key press var  keyS  =  $(window).asEventStream('keypress');

  25. Key press Character map var  keyS  =  $(window).asEventStream('keypress');   var

     charS  =  keyS.map(function(e)  {      return  String.fromCharCode(e.charCode);   });
  26. Key press Character Typed text map fold var  keyS  =

     $(window).asEventStream('keypress');   var  typedText  =  keyS.map(function(e)  {      return  String.fromCharCode(e.charCode);   }).scan('',  function(s,  chr)  {      return  s  +  chr;   });
  27. None
  28. Arrow keys Seconds Key info sampledBy fold Keyboard filter Arrow

    keys Game state onValue Game state Canvas
  29. Juha Paananen “FRP with Bacon.js” http://www.ustream.tv/recorded/29299079

  30. Bret Victor “Inventing on Principle” http://vimeo.com/36579366

  31. THE END!

  32. var  df  =  $.Deferred();   df.then(null,  null,  function(x)  {  

       return  x  *  3;   }).progress(function(x)  {      console.log(x);   });   df.then(null,  null,  function(x)  {      return  x  *  4;   }).progress(function(x)  {      console.log(x);   });   df.notify(3); SIGNALS WITH DEFERRED
  33. var  Signal  =  function(value)  {      this.value  =  value;

         this.callbacks  =  [];   };       Signal.prototype.notify  =  function(value)  {      if  (value  ==  null)  {          return;      }      this.value  =  value;      for  (var  i  =  0;  i  <  this.callbacks.length;  i++)  {          var  callback  =  this.callbacks[i];          callback(value);      }   }; YOUR OWN WITH PURE JS
  34. MAPPING WITH PURE JS Signal.prototype.map  =  function(fn)  {    

     var  childS  =  new  Signal();      if  (this.value  !=  null)  {          childS.value  =  fn(this.value);      }      this.callbacks.push(function(newValue)  {          childS.notify(fn(newValue));      });      return  childS;   };