Introduction to Functional Reactive Programming

D225ebf0faa666ac7655cc7e4689283c?s=47 Daniel Lew
February 04, 2017

Introduction to Functional Reactive Programming

Talk given at GDG DevFest MN 2017. (Recording may be available someday.)

D225ebf0faa666ac7655cc7e4689283c?s=128

Daniel Lew

February 04, 2017
Tweet

Transcript

  1. An Introduction to Functional and Reactive Programming Dan Lew

  2. None
  3. Functional Reactive Programming

  4. Reactive Programming

  5. None
  6. Proactive Passive

  7. public class Switch {
 LightBulb lightBulb;
 
 void onFlip(boolean enabled)

    {
 lightBulb.power(enabled);
 }
 }
  8. Observable Reactive

  9. public static LightBulb create(Switch theSwitch) {
 LightBulb lightBulb = new

    LightBulb();
 theSwitch.addOnFlipListener(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  10. None
  11. Proactive Reactive Who controls LightBulb? Others via power() LightBulb itself

    Who determines what Switch controls? Switch itself Others via listener Is LightBulb synchronous? Synchronous Asynchronous
  12. Modularity • Proactive: Modules control each other • Reactive: Modules

    control themselves
  13. None
  14. None
  15. Why does my db control my UI?

  16. None
  17. public class Switch {
 interface OnFlipListener {
 void onFlip(boolean enabled);


    } void addOnFlipListener(OnFlipListener onFlipListener) {
 // ...etc...
 }
 } • Every listener unique • Code cannot be generalized / built-upon • Every listener requires direct access to Switch • Listenable not something that can be passed around
  18. public class Switch {
 ??? flips() {
 // etc...
 }


    }
  19. Function Returns… One Many Sync Async

  20. Function Returns… One Many Sync T Async

  21. Function Returns… One Many Sync T Iterable<T> Async

  22. Function Returns… One Many Sync T Iterable<T> Async Future<T>

  23. Function Returns… One Many Sync T Iterable<T> Async Future<T> Observable<T>

  24. public class Switch {
 Observable<Boolean> flips() {
 // etc...
 }


    } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> switchObs) {
 LightBulb lightBulb = new LightBulb();
 switchObs.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  25. public class Switch {
 Observable<Boolean> flips() {
 // etc...
 }


    } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> observable) {
 LightBulb lightBulb = new LightBulb();
 switchObs.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  26. public class Switch {
 Observable<Boolean> flips() {
 // etc...
 }


    } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> observable) {
 LightBulb lightBulb = new LightBulb();
 observable.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  27. public class Switch {
 Observable<Boolean> flips() {
 // etc...
 }


    } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> observable) {
 LightBulb lightBulb = new LightBulb();
 observable.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  28. public class Switch {
 Observable<Boolean> flips() {
 // etc...
 }


    } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> observable) {
 LightBulb lightBulb = new LightBulb();
 observable.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  29. Observable • Collection over time • …can have endings… •

    …Or errors
  30. Functional Programming

  31. PURE

  32. int two = add(1, 1); public static int add(int a,

    int b) {
 System.out.println("You're an idiot for using this function!");
 System.exit(1010101);
 return a + b;
 }
  33. int two = add(1, 1); public static int add(int a,

    int b) {
 System.out.println("You're an idiot for using this function!");
 System.exit(1010101);
 return a + b;
 }
  34. int two = add(1, 1); public static int add(int a,

    int b) {
 System.out.println("You're an idiot for using this function!");
 System.exit(1010101);
 return a + b;
 }
  35. int two = add(1, 1); public static int add(int a,

    int b) {
 System.out.println("You're an idiot for using this function!");
 System.exit(1010101);
 return a + b;
 }
  36. int two = add(1, 1); public static int add(int a,

    int b) {
 System.out.println("You're an idiot for using this function!");
 System.exit(1010101);
 return a + b;
 } Side effects SUCK
  37. List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3));
 boolean sumEqualsProduct =

    sum(numbers) == product(numbers); public static int sum(List<Integer> numbers) {
 int total = 0;
 Iterator<Integer> it = numbers.iterator();
 while(it.hasNext()) {
 total += it.next();
 it.remove();
 }
 return total;
 }
  38. List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3));
 boolean sumEqualsProduct =

    sum(numbers) == product(numbers); public static int sum(List<Integer> numbers) {
 int total = 0;
 Iterator<Integer> it = numbers.iterator();
 while(it.hasNext()) {
 total += it.next();
 it.remove();
 }
 return total;
 }
  39. List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3));
 boolean sumEqualsProduct =

    sum(numbers) == product(numbers); public static int sum(List<Integer> numbers) {
 int total = 0;
 Iterator<Integer> it = numbers.iterator();
 while(it.hasNext()) {
 total += it.next();
 it.remove();
 }
 return total;
 } Side effects SUCK
  40. Side Effects • No input List<Spline> reticulateSplines() • No output

    void consume(Food food) • Output cannot be derived from input List<String> getResults(int limit) • Modifies parameters void getHitRect(Rect outRect)
  41. Functional Programming • Pure functions • Immutable data • Higher-order

    functions
  42. public static List<Integer> doubleValues(List<Integer> input) {
 List<Integer> output = new

    ArrayList<>();
 for (Integer value : input) {
 output.add(value * 2);
 }
 return output;
 } Inflexible!
  43. public interface Function {
 Integer apply(Integer int);
 }
 
 public

    static List<Integer> map(List<Integer> input, Function<Integer, Integer> fun) {
 List<Integer> output = new ArrayList<>();
 for (Integer value : input) {
 output.add(fun.apply(value));
 }
 return output;
 }
  44. public interface Function {
 Integer apply(Integer int);
 }
 
 public

    static List<Integer> map(List<Integer> input, Function fun) {
 List<Integer> output = new ArrayList<>();
 for (Integer value : input) {
 output.add(fun.apply(value));
 }
 return output;
 }
  45. public interface Function {
 Integer apply(Integer int);
 }
 
 public

    static List<Integer> map(List<Integer> input, Function fun) {
 List<Integer> output = new ArrayList<>();
 for (Integer value : input) {
 output.add(fun.apply(value));
 }
 return output;
 }
  46. List<Integer> numbers = Arrays.asList(1, 2, 3);
 List<Integer> doubled = map(numbers,

    i -> i * 2);
  47. public interface Function<T, R> {
 R apply(T t);
 }
 


    public static <T, R> List<R> map(List<T> input, Function<T, R> fun) {
 List<R> output = new ArrayList<>();
 for (T value : input) {
 output.add(fun.apply(value));
 }
 return output;
 }
  48. List<Integer> numbers = Arrays.asList(1, 2, 3);
 List<Integer> doubled = map(numbers,

    i -> i * 2); List<String> words = Arrays.asList("one", "two", "three");
 List<Integer> lengths = map(words, s -> s.length());
  49. List<String> words = Arrays.asList("one", "two", "three");
 List<Integer> lengths = map(words,

    s -> s.length());
  50. Back to reactive land…

  51. public class Switch {
 enum State {
 ON,
 OFF
 }


    
 Observable<State> flips() {
 // etc...
 }
 } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> switchObs) {
 LightBulb lightBulb = new LightBulb();
 switchObs.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  52. public class Switch {
 enum State {
 ON,
 OFF
 }


    
 Observable<State> flips() {
 // etc...
 }
 } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> switchObs) {
 LightBulb lightBulb = new LightBulb();
 switchObs.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  53. public class Switch {
 enum State {
 ON,
 OFF
 }


    
 Observable<State> flips() {
 // etc...
 }
 } // Creating the LightBulb… public static LightBulb create(Observable<Boolean> observable) {
 LightBulb lightBulb = new LightBulb();
 observable.subscribe(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  54. None
  55. 
 Switch theSwitch = new Switch(); Observable<State> stateObservable = theSwitch.flips();

    
 Observable<Boolean> booleanObservable = stateObservable
 .map(state -> state == State.ON); 
 LightBulb.create(booleanObservable);
  56. 
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

    theSwitch.flips(); 
 Observable<Boolean> booleanObservable = stateObservable
 .map(state -> state == State.ON); 
 LightBulb.create(booleanObservable);
  57. 
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

    theSwitch.flips(); 
 Observable<Boolean> booleanObservable = stateObservable
 .map(state -> state == State.ON); 
 LightBulb.create(booleanObservable);
  58. 
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

    theSwitch.flips(); 
 Observable<Boolean> booleanObservable = stateObservable
 .map(state -> state == State.ON); 
 LightBulb.create(booleanObservable);
  59. 
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

    theSwitch.flips(); 
 Observable<Boolean> booleanObservable = stateObservable
 .map(state -> state == State.ON); 
 LightBulb.create(booleanObservable);
  60. None
  61. teams boards

  62. teams boards combineLatest

  63. • create • defer • from • interval • just

    • range • repeat • timer • buffer • map • flatMap • switchMap • groupBy • scan • reduce • window • debounce • distinct • elementAt • filter • first • last • ignoreElements • sample • skip • skipLast • skipWhile • take • takeList • takeUntil • combineLatest • zip • merge • concat • amb • startWith • do • observeOn • subscribeOn • delay • publish • throttle • timestamp • retry
  64. Functional Reactive Programming • Reactive streams • Functional operators

  65. But why? • Reactive streams • Modularity • Inherently asynchronous

    • Functional operators • Control flow of streams • Reproduce common logic
  66. Resources • RxJava introduction: http://blog.danlew.net/2014/09/15/grokking- rxjava-part-1/ • Stream explanation: https://cycle.js.org/streams.html

    • Reactive duality: https://goo.gl/F2OyVp • Learn you a Haskell: learnyouahaskell.com
  67. Thanks! • @danlew42 • danlew.net