Strictness and Laziness

Functional Programming in Java

Created by Mark Perry, @mprry, G+, Blog, LinkedIn, GitHub, maperry78@yahoo.com.au

Motivation

  • Previously used map, fold, filter and bind over Lists
  • Composition over lists inefficient
  • 
    List.list(1, 2, 3, 4)
        .map(i -> i + 10)
        .filter(i -> i % 2 == 0)
        .map(i -> i  * 3);
    // List.list(36,42)
    						
  • Inefficient memory usage - intermediate states
  • Build better List
  • Laziness improves modularity

Lazy Values

interface F0<A> {
    A f();
}
abstract class P1<A> implements F0<A> {
    abstract A _1();
    A f() {...}
    P1<B> map(F<A, B> f) {...}
    P1<B> bind(F<A, P1<B>> f) {...}
    P1<A> join(P1<P1<A>> p) {...}
    P1<C> liftM2(P1<B> p, F<A, B, C> f) {...}
    // more methods
}
abstract class P2<A, B> {
    abstract A _1();
    abstract B _2();
    // more methods
}

Creating Values

public static P1<A> p(A a) {
    return new P1<A>() {
        A _1() {
            return a;
        }
    };
}
P1<Integer> p1 = P.p(1);

public static P1<A> lazy(F0<A> f) {
    return new P1<A>() {
        A _1() {
            return f.f();
        }
    };
}
P1<Integer> p2 = P.lazy(() -> intFunction());

Unfold

  • Unfold is co-recursive - what?
  • Recursion consumes data and terminates
  • Co-recursion produces data and is productive (co-terminates)
  • Can always evaluate more in finite time

Summary

  • Laziness is efficient and modular
  • Separate description of infinite expression and evaluation
  • Reuse description in different contexts
  • Functions can evaluate different portion of infinite stream

Afterword

  • Functional Programming in Scala, Chiusano and Bjarnason
  • Chapter 5, Strictness and Laziness

Created by Mark Perry, @mprry, G+, Blog, LinkedIn, GitHub, maperry78@yahoo.com.au