Duke LambdaPurpose of this post is to provide a glimpse of the new features included in Java 8 that shift this language towards a more Functional Programming paradigm. But before, let’s define what we understand for Functional Programming (FP). Functional programming key characteristics include:

  • Higher Order Functions
  • Pure Functions and Immutability
  • Tail Call Recursion

Higher Order Functions for a FP language means that functions are considered first class citizens, allowing the programmer to use them as any other value the language defines, for example, a Function value:

  • can be assigned to a variable defined with a proper type
  • can be passed or returned to/from another functions, allowing functions to be composed or _curried_ (partially applied).

Pure Functions are those functions that don’t produce side effects. Instead of directly modifying data structures within the function body, those data structures are returned as result of the invocation. This behaviour results in Immutable data structures, which are far less error prone than classical mutable data structures.

Tail recursion

Tail Call Recursion allows a compiler to reuse a call stack frame in a recursive algorithm, making the execution behave (in terms of memory allocation) as if it were an iterative algorithm. Instead of allocating new stack frames for every recursive call, if the structure of the call follows an specific pattern, the compiler then can reuse same frame, making possible the use recursion without any increase in program’s memory footprint.

Tail Call Optimization

So, what does Java 8 include in order to make FP paradigm closer to the programmer? The key feature included in this release is are Lambda Expressions.

But what’s a Lambda Expression? Well, it just a syntactic sugar included in the language,  reducing the amount of code needed to work with anonymous classes. Lambdas’ its syntax kind of reminds of a closure or monad, but let’s better see an example of a lambda:

 System.out.println("Hello Lambdas!");

But, as previously said, this could also be defined as anonymous class, as this is just syntactic sugar (let’s assume that LambadInterface is an already defined interface with one method apply):

new LambdaInterface {
   @Override
   public void apply() {
      System.out.println("Hello... Lambdas?");
   }
};

Not quite the same? Let’s evolve these pieces of code a little bit further:

 System.out.println("Hello Lambdas!");
lamdba.apply(); // Hello Lambdas!

LambdaInterface lambda = new LambdaInterface {
   public void apply() {
      System.out.println("Hello... Lambdas?");
   }
};
lamdba.apply(); // Hello... Lambdas?

How do Lambdas differ from FP Closures? Well, a closure is an anonymous function packed with the context where it was defined, being able to modify it’s context (context defined variables are, in fact, closed) . Java 8 Lambdas can access external context variables but only if they’re defined as final or if the programmer assures that they are not going to change their value (are actually final).

We said that Function Composition is also another key characteristic of FP, so, are Lambdas composable? Let’s see an actual example of Lambdas composition in action:

 n * 2;
Function<Integer, Integer> increment = (n) -> n + 1;

Function<Integer, Integer> doublePlusOne = duplicate.andThen(increment);

Unfortunately, Tail recursion is not included in Java 8, so we’ll still have to be cautious with memory consumption in recursive algorithms.

In future posts, we’ll deep into Lambdas and Functional Interfaces, and how they allow us to create a cleaner and more expressive code.