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 full-size slide

  2. Functional Reactive
    Programming

    View full-size slide

  3. Reactive Programming

    View full-size slide

  4. Proactive Passive

    View full-size slide

  5. public class Switch {

    LightBulb lightBulb;


    void onFlip(boolean enabled) {

    lightBulb.power(enabled);

    }

    }

    View full-size slide

  6. Observable Reactive

    View full-size slide

  7. public static LightBulb create(Switch theSwitch) {

    LightBulb lightBulb = new LightBulb();

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

    return lightBulb;

    }

    View full-size slide

  8. 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 full-size slide

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

    View full-size slide

  10. Why does my db control my UI?

    View full-size slide

  11. 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 full-size slide

  12. public class Switch {

    ??? flips() {

    // etc...

    }

    }

    View full-size slide

  13. Function Returns…
    One Many
    Sync
    Async

    View full-size slide

  14. Function Returns…
    One Many
    Sync T
    Async

    View full-size slide

  15. Function Returns…
    One Many
    Sync T Iterable
    Async

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  18. 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 full-size slide

  19. 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 full-size slide

  20. 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 full-size slide

  21. 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 full-size slide

  22. 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 full-size slide

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

    View full-size slide

  24. Functional Programming

    View full-size slide

  25. 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 full-size slide

  26. 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 full-size slide

  27. 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 full-size slide

  28. 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 full-size slide

  29. 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 full-size slide

  30. 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 full-size slide

  31. 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 full-size slide

  32. 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 full-size slide

  33. 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 full-size slide

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

    View full-size slide

  35. public static List doubleValues(List input) {

    List output = new ArrayList<>();

    for (Integer value : input) {

    output.add(value * 2);

    }

    return output;

    }
    Inflexible!

    View full-size slide

  36. 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 full-size slide

  37. 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 full-size slide

  38. 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 full-size slide

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

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

    View full-size slide

  40. 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 full-size slide

  41. 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 full-size slide

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

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

    View full-size slide

  43. Back to reactive land…

    View full-size slide

  44. 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 full-size slide

  45. 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 full-size slide

  46. 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 full-size slide


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

    Observable booleanObservable = stateObservable

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

    LightBulb.create(booleanObservable);

    View full-size slide


  48. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

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

    LightBulb.create(booleanObservable);

    View full-size slide


  49. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

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

    LightBulb.create(booleanObservable);

    View full-size slide


  50. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

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

    LightBulb.create(booleanObservable);

    View full-size slide


  51. Switch theSwitch = new Switch();

    Observable stateObservable = theSwitch.flips();

    Observable booleanObservable = stateObservable

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

    LightBulb.create(booleanObservable);

    View full-size slide

  52. teams
    boards
    combineLatest

    View full-size slide

  53. • 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 full-size slide

  54. Functional Reactive Programming
    • Reactive streams
    • Functional operators

    View full-size slide

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

    View full-size slide

  56. 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 full-size slide

  57. Thanks!
    • @danlew42
    • danlew.net

    View full-size slide