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

Introduction to Functional Reactive Programming

Daniel Lew
February 04, 2017

Introduction to Functional Reactive Programming

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

Daniel Lew

February 04, 2017
Tweet

More Decks by Daniel Lew

Other Decks in Programming

Transcript

  1. An Introduction to Functional
    and Reactive Programming
    Dan Lew

    View Slide

  2. View Slide

  3. Functional Reactive
    Programming

    View Slide

  4. Reactive Programming

    View Slide

  5. View Slide

  6. Proactive Passive

    View Slide

  7. public class Switch {

    LightBulb lightBulb;


    void onFlip(boolean enabled) {

    lightBulb.power(enabled);

    }

    }

    View Slide

  8. Observable Reactive

    View Slide

  9. public static LightBulb create(Switch theSwitch) {

    LightBulb lightBulb = new LightBulb();

    theSwitch.addOnFlipListener(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  10. View Slide

  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

    View Slide

  12. Modularity
    • Proactive: Modules control each other
    • Reactive: Modules control themselves

    View Slide

  13. View Slide

  14. View Slide

  15. Why does my db control my UI?

    View Slide

  16. View Slide

  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

    View Slide

  18. public class Switch {

    ??? flips() {

    // etc...

    }

    }

    View Slide

  19. Function Returns…
    One Many
    Sync
    Async

    View Slide

  20. Function Returns…
    One Many
    Sync T
    Async

    View Slide

  21. Function Returns…
    One Many
    Sync T Iterable
    Async

    View Slide

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

    View Slide

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

    View Slide

  24. public class Switch {

    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable switchObs) {

    LightBulb lightBulb = new LightBulb();

    switchObs.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  25. public class Switch {

    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable observable) {

    LightBulb lightBulb = new LightBulb();

    switchObs.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  26. public class Switch {

    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable observable) {

    LightBulb lightBulb = new LightBulb();

    observable.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  27. public class Switch {

    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable observable) {

    LightBulb lightBulb = new LightBulb();

    observable.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  28. public class Switch {

    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable observable) {

    LightBulb lightBulb = new LightBulb();

    observable.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  29. Observable
    • Collection over time
    • …can have endings…
    • …Or errors

    View Slide

  30. Functional Programming

    View Slide

  31. PURE

    View Slide

  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;

    }

    View Slide

  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;

    }

    View Slide

  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;

    }

    View Slide

  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;

    }

    View Slide

  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

    View Slide

  37. List numbers = new ArrayList<>(Arrays.asList(1, 2, 3));

    boolean sumEqualsProduct = sum(numbers) == product(numbers);
    public static int sum(List numbers) {

    int total = 0;

    Iterator it = numbers.iterator();

    while(it.hasNext()) {

    total += it.next();

    it.remove();

    }

    return total;

    }

    View Slide

  38. List numbers = new ArrayList<>(Arrays.asList(1, 2, 3));

    boolean sumEqualsProduct = sum(numbers) == product(numbers);
    public static int sum(List numbers) {

    int total = 0;

    Iterator it = numbers.iterator();

    while(it.hasNext()) {

    total += it.next();

    it.remove();

    }

    return total;

    }

    View Slide

  39. List numbers = new ArrayList<>(Arrays.asList(1, 2, 3));

    boolean sumEqualsProduct = sum(numbers) == product(numbers);
    public static int sum(List numbers) {

    int total = 0;

    Iterator it = numbers.iterator();

    while(it.hasNext()) {

    total += it.next();

    it.remove();

    }

    return total;

    }
    Side effects SUCK

    View Slide

  40. Side Effects
    • No input
    List reticulateSplines()
    • No output
    void consume(Food food)
    • Output cannot be derived from input
    List getResults(int limit)
    • Modifies parameters
    void getHitRect(Rect outRect)

    View Slide

  41. Functional Programming
    • Pure functions
    • Immutable data
    • Higher-order functions

    View Slide

  42. public static List doubleValues(List input) {

    List output = new ArrayList<>();

    for (Integer value : input) {

    output.add(value * 2);

    }

    return output;

    }
    Inflexible!

    View Slide

  43. public interface Function {

    Integer apply(Integer int);

    }


    public static List map(List input,
    Function fun) {

    List output = new ArrayList<>();

    for (Integer value : input) {

    output.add(fun.apply(value));

    }

    return output;

    }

    View Slide

  44. public interface Function {

    Integer apply(Integer int);

    }


    public static List map(List input,
    Function fun) {

    List output = new ArrayList<>();

    for (Integer value : input) {

    output.add(fun.apply(value));

    }

    return output;

    }

    View Slide

  45. public interface Function {

    Integer apply(Integer int);

    }


    public static List map(List input,
    Function fun) {

    List output = new ArrayList<>();

    for (Integer value : input) {

    output.add(fun.apply(value));

    }

    return output;

    }

    View Slide

  46. List numbers = Arrays.asList(1, 2, 3);

    List doubled = map(numbers, i -> i * 2);

    View Slide

  47. public interface Function {

    R apply(T t);

    }


    public static List map(List input,
    Function fun) {

    List output = new ArrayList<>();

    for (T value : input) {

    output.add(fun.apply(value));

    }

    return output;

    }

    View Slide

  48. List numbers = Arrays.asList(1, 2, 3);

    List doubled = map(numbers, i -> i * 2);
    List words = Arrays.asList("one", "two", "three");

    List lengths = map(words, s -> s.length());

    View Slide

  49. List words = Arrays.asList("one", "two", "three");

    List lengths = map(words, s -> s.length());

    View Slide

  50. Back to reactive land…

    View Slide

  51. public class Switch {

    enum State {

    ON,

    OFF

    }


    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable switchObs) {

    LightBulb lightBulb = new LightBulb();

    switchObs.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  52. public class Switch {

    enum State {

    ON,

    OFF

    }


    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable switchObs) {

    LightBulb lightBulb = new LightBulb();

    switchObs.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  53. public class Switch {

    enum State {

    ON,

    OFF

    }


    Observable flips() {

    // etc...

    }

    }
    // Creating the LightBulb…
    public static LightBulb create(Observable observable) {

    LightBulb lightBulb = new LightBulb();

    observable.subscribe(enabled -> lightBulb.power(enabled));

    return lightBulb;

    }

    View Slide

  54. View Slide


  55. Switch theSwitch = new Switch();
    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

    .map(state -> state == State.ON);

    LightBulb.create(booleanObservable);

    View Slide


  56. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

    .map(state -> state == State.ON);

    LightBulb.create(booleanObservable);

    View Slide


  57. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

    .map(state -> state == State.ON);

    LightBulb.create(booleanObservable);

    View Slide


  58. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

    .map(state -> state == State.ON);

    LightBulb.create(booleanObservable);

    View Slide


  59. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

    .map(state -> state == State.ON);

    LightBulb.create(booleanObservable);

    View Slide

  60. View Slide

  61. teams
    boards

    View Slide

  62. teams
    boards
    combineLatest

    View Slide

  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

    View Slide

  64. Functional Reactive Programming
    • Reactive streams
    • Functional operators

    View Slide

  65. But why?
    • Reactive streams
    • Modularity
    • Inherently asynchronous
    • Functional operators
    • Control flow of streams
    • Reproduce common logic

    View Slide

  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

    View Slide

  67. Thanks!
    • @danlew42
    • danlew.net

    View Slide