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

Javaslang - functional Java done right

Javaslang - functional Java done right

Grzegorz Piwowarek

July 02, 2016
Tweet

More Decks by Grzegorz Piwowarek

Other Decks in Programming

Transcript

  1. Javaslang - functional Java
    done right
    Grzegorz Piwowarek
    [email protected]
    1

    View Slide

  2. Me
    [email protected]
    Yoyo Player
    Musician
    2

    View Slide

  3. [email protected]
    Twitter
    GitHub
    3

    View Slide

  4. pivovarit#2152
    4

    View Slide

  5. Java 8
    5

    View Slide

  6. "Functional" Java8:
    Lambda Expressions
    Optional, Stream, CompletableFuture
    ...
    6

    View Slide

  7. 7

    View Slide

  8. Java 8 issues:
    No functional data structures
    No memoization, no lifting
    No pattern matching
    No Tuple
    Only 3 monadic containers
    Lack of Stream/Optional in APIs
    Checked exceptions in functions
    Type pollution
    list.stream().map(...).collect(toList())
    ...
    8

    View Slide

  9. List foo(List list);
    9

    View Slide

  10. List foo(List list) {
    if (this.state.isEmpty() || list.isEmpty()) {
    throw new IllegalStateException("Ouch...");
    }
    list.add(this.state.get(0));
    list.add(CONSTANT);
    this.moreState.addAll(list);
    OtherClass.mutableStaticField = list;
    return list;
    }
    10

    View Slide

  11. Potential inputs:
    params
    Potential outputs:
    returned value
    11

    View Slide

  12. Potential inputs:
    params
    instance state
    global state
    Potential outputs:
    returned value
    mutable instance state
    mutable global state
    mutable params
    exceptions
    12

    View Slide

  13. Immutability
    Referential
    Transparency
    13

    View Slide

  14. Functional programming is not
    about lambdas.
    14

    View Slide

  15. "Functional programming is about writing pure functions,
    about removing hidden inputs and outputs as far as we can,
    so that as much of our code as possible
    just describes a relationship between inputs and outputs."
    http://blog.jenkster.com/2015/12/what-is-functional-programming.html
    15

    View Slide

  16. Java Collections API:
    add()
    remove()
    clear()
    ...
    16

    View Slide

  17. final Date date = new Date();
    final HashMap map = new HashMap<>();
    map.put(date, "some value");
    date.setTime(123);
    map.containsKey(date); // false
    17

    View Slide

  18. 18

    View Slide

  19. λ
    Tuple
    Value
    19

    View Slide

  20. λ
    Function2 sum = (a, b) -> a + b;
    CheckedFunction2 sum = (a, b) -> a + b;
    composition
    lifting
    currying
    memoization
    20

    View Slide

  21. Lifting
    Function2 divideBy = (a, b) -> a / b;
    Function2> lift = lift(divideBy);
    21

    View Slide

  22. Currying
    Function2 sum = (a, b) -> a + b;
    Function1 add2 = add.curried().apply(2);
    22

    View Slide

  23. Memoization
    Function2 sum = (a, b) -> a + b;
    Function2 memoizedSum = sum.memoized();
    23

    View Slide

  24. Function0 memoizedRand = Function0.of(Math::random).memoized();
    double randomValue1 = memoizedRand.apply();
    double randomValue2 = memoizedRand.apply();
    then(randomValue1).isEqualTo(randomValue2);
    24

    View Slide

  25. Tuple
    Tuple2 java8 = Tuple.of("Java", 8);
    Tuple2 that = java8.map(
    s -> s + "slang",
    i -> i / 4
    );
    String transform = java8.transform((s, i) -> s + i);
    Iterable> objects = java8.toSeq()
    25

    View Slide

  26. Value
    Option
    Try
    Lazy
    Either
    Future
    Validation
    Collections API
    public interface Value extends Iterable
    26

    View Slide

  27. Option
    27

    View Slide

  28. final String result = Option.of(somethingNullable)
    .map(Object::toString)
    .map(String::toLowerCase)
    .getOrElse(() -> "DEFAULT VALUE");
    28

    View Slide

  29. List> list = Arrays
    .asList(Optional.of(1), Optional.empty(), Optional.of(3));
    list.stream()
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(toList());
    List list = List.of(Option.of(1), Option.none());
    list.flatMap(o -> o);
    Java 8
    Javaslang
    29

    View Slide

  30. Try
    30

    View Slide

  31. Try.of(() -> new URI("bebebe"))
    .map(URI::getScheme)
    .getOrElse(() -> "UNKNOWN");
    31

    View Slide

  32. Lazy
    32

    View Slide

  33. Lazy lazy = Lazy.of(this::veryLongComputation)
    .map(Object::toString)
    .map(String::toUpperCase);
    lazy.get();
    33

    View Slide

  34. Functional Data
    Structures
    34

    View Slide

  35. Functional Data Structures:
    Persistent
    Immutable
    with Referential Transparent methods
    35

    View Slide

  36. Seq
    36

    View Slide

  37. 37

    View Slide

  38. public static Stream fibonacci() {
    return Stream.of(1, 1)
    .appendSelf(self -> self.zip(self.tail())
    .map(t -> t._1 + t._2));
    }
    38

    View Slide

  39. Pattern Matching
    39

    View Slide

  40. String on = Match(i).of(
    Case(x -> x % 2 == 0, "Even"),
    Case(x -> x % 2 == 1, "Odd"),
    Case($(), "?"));
    Option on = Match(i).option(
    Case(x -> x % 2 == 0, "Even"),
    Case(x -> x % 2 == 1, "Odd"));
    40

    View Slide

  41. String on = Match(i).of(
    Case($(1), "One"),
    Case($(2), "Two"),
    Case($(), "Something else"));
    41

    View Slide

  42. Match(localDate).of(
    Case(LocalDate(2016, 2, 13), () -> "2016-02-13"),
    Case(LocalDate(2016, $(), $_), m -> "month " + m + " in 2016"),
    Case(LocalDate($(2016), $(), $_), (y, m) -> "my" + m + y),
    Case($_, () -> "(catch all)")
    );
    42

    View Slide

  43. Match(i).of(
    Case(is(1), "1"),
    Case(isIn(2, 3), "2 or 3"),
    Case(anyOf(is(4), noneOf(is(5), is(6))), "4 or not (5 or 6)"),
    Case(instanceOf(String.class), "String content"),
    Case($(), "?")
    );
    http://koziolekweb.pl/2016/06/18/pattern-matching-w-javie-z-javaslang-ii/
    43

    View Slide

  44. Try.of(this::doSomething)
    .recover(x -> Match(x).of(
    Case(instanceOf(Exception_1.class), ...),
    Case(instanceOf(Exception_2.class), ...),
    Case(instanceOf(Exception_n.class), ...)
    ))
    .getOrElse(other);
    44

    View Slide

  45. www.javaslang.io
    45

    View Slide

  46. View Slide