Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Codemotion 2015 - Functional Reactive Programming: FP, Javascript con extra de bacon

Codemotion 2015 - Functional Reactive Programming: FP, Javascript con extra de bacon

Javier Onielfa

November 28, 2015

More Decks by Javier Onielfa

Other Decks in Programming


  1. Summary 1. Functional Programming 2. Theory a. Classical FRP b.

    Transformations 3. Coding a. Architecture b. Examples 4. Implementations and problems a. Advantages/Disavantages b. Implementation 5. References
  2. Functional Programming • Functional programming is programming with functions •

    Functions are first class citizens: You can pass them, return them and store them in datastructures. • Functions tend to be pure. The evaluation of a function ONLY depends on its inputs. • Equational reasoning. • Embraces a data-oriented view. You are transforming data.

  4. Facing values that change over time app.post('/process-file', function(req, res) {

    var inputFile = 'input.txt'; var outputFile = 'output.txt'; fs.readFile(inputFile, function(err, data) { if (err) return res.status(500).send(err); process1(data, function(err, data) { if (err) return res.status(500).send(err); process2(data, function(err, data) { if (err) return res.status(500).send(err); process3(data, function(err, data) { if (err) return res.status(500).send(err); fs.writeFile(outputFile, data, function(err) { if (err) return res.status(500).send(err); res.status(200).send('processed successfully using callback hell'); }); }); }); }); }); });
  5. Classic FRP As semantically defined in Functional Reactive Animation, Conal

    Elliot et al, 1998. Behavior • It’s a function of time ◦ type Behavior :: T -> a • Continuous time-varying values. • Sample rate independent. • Introduced for modelling animation/physics (velocity, gravity,etc) • Inefficient implementation. Led to space leaks.
  6. Classic FRP As semantically defined in Functional Reactive Animation, Conal

    Elliot et al, 1998. EventSource • Stream of timed values. ◦ type EventSource :: [(T,a)] where Tn < Tn+1 • Discrete time values. • It’s like you are in another dimension where you can see the past, present and future. The whole timeline. • Fits perfectly for heavily event oriented applications.
  7. “There is no future. There is no past… Time is

    simultaneous, an intricately structured jewel that humans insist on viewing one edge at a time, when the whole design is visible in every facet.” Dr. Manhattan, Watchmen
  8. C 1s Keystrokes O 3s D E 7s M 9s

    O 12s 4s Keystrokes = [(1,’C’),(3,’O’),(4,’D’),(7,’E’),(9,’M’),(12,’O’), (14,’T’),(17,’I’)] I 17s T 14s Event Source
  9. C 1s Ks O 3s D E 7s M 9s

    O 12s 4s Map f(v) = toLowerCase(v) c 1s Ks.map(f) o 3s d e 7s m 9s o 12s 4s 14s t 14s T
  10. C 1s Ks O 3s D E 7s M 9s

    O 12s 4s Filter f(v) = return v == ‘o’; ks.filter(f) o 3s o 12s 14s T
  11. Es1 1 3s 2 12s Merge 14s 3 Es2 B

    C 7s D 9s 4s A 1s Es1.merge(Es2) 1 3s B C 7s D 9s 2 12s 4s 14s 3 A 1s
  12. 1 1s c 1 3s 1 1 7s 1 9s

    1 12s 4s Scan plus(a,b) = return a+b; c.scan(0,plus) 14s 1 1 1s 2 3s 3 4 7s 5 9s 6 12s 4s 14s 7
  13. How do I create an EventStream? • From jQuery/Zepto object:

    ◦ $(‘#mydiv’).asEventStream(‘click’) • From promise object: ◦ Bacon.fromPromise($.ajax(“/search/”+query”)) • From DOM event: ◦ Bacon.fromEvent(document.body, ‘click’) • One-event eventstream: ◦ Bacon.once(‘Hello’) • Interval: ◦ Bacon.interval(1000, ‘Tick’)
  14. Architecture of an FRP app Event Stream ... Event Stream

    Event Stream Merge Model Transformation Side Effects ... Side Effects Side Effects
  15. Simple Up/Down example var up = $('#upButton').asEventStream('click'); var down =

    $('#downButton').asEventStream('click'); var counter = up .map(1) .merge(down.map(-1)) .scan(0, (acc, val) => return acc + val;); counter.assign($('#result'), 'text');
  16. Name Keyup Stream Min Keyup Stream Merge to Model Filter

    Valid Form validation example Max Keyup Stream Enable Submit Show error msg
  17. Form validation example // Input streams var nameStream = $('#name')

    .asEventStream('keyup') .map(event => return event.target.value;) .skipDuplicates() .toProperty($('#name').val()); var minStream = $('#min') .asEventStream('keyup') .map(event => return parseInt(event.target.value);) .skipDuplicates() .toProperty(parseInt($('#min').val()));
  18. Form validation example // Model Stream var modelStream = Bacon.combineTemplate({

    name: nameStream, min: minStream, max: maxStream });
  19. Form validation example //Side effects evaluateStream.map(m => return !m.valid;) .assign($('#submitButton'),

    'attr', 'disabled'); evaluateStream.map(m => return m.message;) .assign($('#error'), 'text');
  20. Shape designer example // Input streams var colorStream = $('#color').asEventStream('change')

    .map(event => return event.target.value;) .skipDuplicates() .toProperty($('#color').val()) .map(c => transformColor(c));
  21. Shape designer example // SideEffects var canvas = document.getElementById("canvas"); var

    ctx = canvas.getContext('2d'); modelStream.onValue(m => { drawModel(ctx, m); });
  22. Tweet Stream North Filter Transform Twitter Map example (Client) Merge

    South Filter Transform Put Marker Write Tweet
  23. var tweetStream = Bacon.fromEvent(socket, 'tweet'); var northStream = tweetStream.filter(inNorth) .map(t

    => return t.text + ' (N)';); var southStream = tweetStream.filter(inSouth) .map(t => return t.text + ' (S)';); var finalStream = northStream.merge(southStream); finalStream.onValue(t => { putMarker(t); writeTweet(t); }); Twitter Map example (Client)
  24. Advantages • It allows you to define time-dependent application in

    a declarative way. • Time-varying values are first class citizen. • It allows you to use a data transformation style using mostly pure functions. • Side-effects are confined to one part of the application
  25. Problems • What if one transformation function consumes too much

    time? • What if one EventStream is too fast for the system to process? • What if one EventStream in a zip is way faster than the other one?
  26. Implementation • Pull-based ◦ Demand-driven. Sampling of the reactive EventStreams.

    • Push-based ◦ It can be implemented on top of event loops. • Infinite vs finite ◦ (Bacon.js) Streams are finite: They can start and end at arbitrary moments. ◦ (Elm) Streams are infinite: Stream are always “producing” values (Hot/Cold).
  27. Libraries • JS : Bacon.js, RxJs, “Elm” • Java: RxJava

    • C#: Rx.Net • Objective-C: ReactiveCocoa • Ruby: Frapuccino • Python: RxPy
  28. References, Links and Videos • Functional Reactive Animation, Conal Elliot

    et al, 1998 • Push-Pull Functional Reactive Programming, Conal Elliot • Deprecating the observer pattern, Martin Odersky et al • React 2014: Erik Meijer - What does it mean to be Reactive? • “Controlling Time and Space: understanding the many formulations of FRP” by Evan Czaplicki (Elm creator) • Ryan Trinkle - Reflex: Practical Functional Reactive Programming (Haskell) • Lambda Jam 2014 - Conal Elliot - The Essence and Origins of Functional Reactive Programming