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. 2.
  2. 5.
  3. 9.

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

    LightBulb();
 theSwitch.addOnFlipListener(enabled -> lightBulb.power(enabled));
 return lightBulb;
 }
  4. 10.
  5. 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
  6. 13.
  7. 14.
  8. 16.
  9. 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
  10. 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;
 }
  11. 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;
 }
  12. 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;
 }
  13. 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;
 }
  14. 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;
 }
  15. 31.
  16. 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;
 }
  17. 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;
 }
  18. 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;
 }
  19. 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;
 }
  20. 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
  21. 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;
 }
  22. 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;
 }
  23. 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
  24. 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)
  25. 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!
  26. 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;
 }
  27. 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;
 }
  28. 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;
 }
  29. 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;
 }
  30. 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());
  31. 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;
 }
  32. 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;
 }
  33. 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;
 }
  34. 54.
  35. 55.

    
 Switch theSwitch = new Switch(); Observable<State> stateObservable = theSwitch.flips();

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

    
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

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

    
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

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

    
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

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

    
 Switch theSwitch = new Switch(); 
 Observable<State> stateObservable =

    theSwitch.flips(); 
 Observable<Boolean> booleanObservable = stateObservable
 .map(state -> state == State.ON); 
 LightBulb.create(booleanObservable);
  40. 60.
  41. 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
  42. 65.

    But why? • Reactive streams • Modularity • Inherently asynchronous

    • Functional operators • Control flow of streams • Reproduce common logic