Functional Reactive Programming in Clojurescript

10,655 views

Published on

FRP Talk given at LambdaJam Australia 2013

Published in: Technology, Sports

Functional Reactive Programming in Clojurescript

  1. 1. Taming asynchronousworkflows with FunctionalReactive ProgrammingLambdaJam - Brisbane, 2013Leonardo Borges@leonardo_borgeswww.leonardoborges.comwww.thoughtworks.comFriday, 17 May 13
  2. 2. Leonardo Borges@leonardo_borgeswww.leonardoborges.comwww.thoughtworks.com• Thoughtworker• Functional Programming enthusiast• Clojure Evangelist• Founder & Organiser of the SydneyClojure User Group (clj-syd)• World traveller• Fan of Murray’s Beers :)about:meFriday, 17 May 13
  3. 3. Functional programmers likeprogramming with values:a, b, c...and pure functions:f, g, h...Friday, 17 May 13
  4. 4. We get new values by applyingfunctions to it(f a) ;;=> bFriday, 17 May 13
  5. 5. But that’s hardly useful whenwe have multiple values(def vals [a b c])Friday, 17 May 13
  6. 6. So we use Higher OrderFunctions(map f vals)Friday, 17 May 13
  7. 7. And compose them as we see fit(-> vals(filter f)(map g)(reduce h))Friday, 17 May 13
  8. 8. But what if the value isn’tknown...yet?a?Friday, 17 May 13
  9. 9. We make promises;; thread#1(def a (promise));; ...later in the program(f @a) ;;<= blocks thread;; thread#2(deliver a 10) ;; now thread#1 continuesFriday, 17 May 13
  10. 10. Not great if we want to ‘react’to a new valueFriday, 17 May 13
  11. 11. What about a list of - as of yetunknown - values?[a,b,c]? ? ?Friday, 17 May 13
  12. 12. Or better yet, a value thatchanges over time?037.575112.515010s 20s 30s 40s 50s 60ValueTimeFriday, 17 May 13
  13. 13. Does this sound familiar?Friday, 17 May 13
  14. 14. Spreadsheets: a poor man’sreactive programming modelValuesFunctionFriday, 17 May 13
  15. 15. Spreadsheets: a poor man’sreactive programming modelAs we changea valueOur function cellreacts to thechangeFriday, 17 May 13
  16. 16. ‘Changing a value’ is an eventSeveral events over time form anevent streamFriday, 17 May 13
  17. 17. “Functional ReactiveProgramming is about effectivelyprocessing event streams withoutexplicitly managing state”- meFriday, 17 May 13
  18. 18. “FRP is about handling time-varying values like they wereregular values.”- Haskell wikiFriday, 17 May 13
  19. 19. We’ll use Reactive Extensions(Rx) - but there are manyimplementationsFriday, 17 May 13
  20. 20. In Rx, event streams are calledObservable sequencesFriday, 17 May 13
  21. 21. Rx 101(-> (.returnValue js/Rx.Observable 42)(.map #(* % 2))(.subscribe #(.log js/console %)));; 84Friday, 17 May 13
  22. 22. Rx 101(-> (.fromArray js/Rx.Observable(clj->js [10 20 30]))(.map #(* % 2))(.reduce +)(.subscribe #(.log js/console %)));; 120Friday, 17 May 13
  23. 23. Rx 101(defn project-range [n](.returnValue js/Rx.Observable (range n)))(-> (.fromArray js/Rx.Observable(clj->js [1 2 3]))(.selectMany project-range)(.subscribe #(.log js/console (clj->js %))));; [0];; [0 1];; [0 1 2]Friday, 17 May 13
  24. 24. Observables are MonadsFriday, 17 May 13
  25. 25. The Monad Type Classclass Monad m wherereturn :: a -> m a(>>=) :: m a -> (a -> m b) -> m bFriday, 17 May 13
  26. 26. Monad functions: returnreturn :: a -> m areturnValue :: a -> Observable aFriday, 17 May 13
  27. 27. (>>=) :: m a -> (a -> m b) -> m bselectMany :: Observable a -> (a -> Observable b) -> Observable bMonad functions: >>= (bind)Friday, 17 May 13
  28. 28. Demo: Simple polling appFriday, 17 May 13
  29. 29. Server exposes poll questionsand resultse.g.:{:id 7:question "Which is the best music style?":results {:a 10:b 47:c 17}}Friday, 17 May 13
  30. 30. What we want• Render results• Continuously poll server every 2 secs• If current question is the same as the previous oneupdate results;• Otherwise:• Stop polling;• Display countdown message;• Render new question and results;• Restart polling;Friday, 17 May 13
  31. 31. The core ideaFriday, 17 May 13
  32. 32. Turn server results into anevent stream112334Friday, 17 May 13
  33. 33. Duplicate stream, skipping one112334123345skip 1Friday, 17 May 13
  34. 34. Zip them together11233412zip23333445 11233451Friday, 17 May 13
  35. 35. Now we have access to boththe previous and currentresults, with no local variablesFriday, 17 May 13
  36. 36. Show me the code!https://github.com/leonardoborges/frp-codeFriday, 17 May 13
  37. 37. (def results-connectable(let [obs (-> js/Rx.Observable(.interval 2000)(.selectMany results-observable)(.publish)(.refCount))obs-1 (.skip obs 1)](.zip obs obs-1 (fn [prev curr]{:prev prev:curr curr}))))Turn server results into an event stream{The core ideaClone stream, skip oneZip them together{Friday, 17 May 13
  38. 38. “FRP is about handling time-varying values like they wereregular values.”- Haskell wikiFriday, 17 May 13
  39. 39. Questions?Leonardo Borges@leonardo_borgeswww.leonardoborges.comwww.thoughtworks.comFriday, 17 May 13
  40. 40. ReferencesCode - https://github.com/leonardoborges/frp-codeRxJS - https://github.com/Reactive-Extensions/RxJSRxJava - https://github.com/Netflix/RxJavaOther FRP implementations:Reactive-banana - http://www.haskell.org/haskellwiki/Reactive-bananaJavelin (Clojurescript) - https://github.com/tailrecursion/javelinBacon.js - https://github.com/raimohanska/bacon.jsFriday, 17 May 13

×