Functional Programming in Java

As I stated in my previous post I’m deep diving into Java because that’s the primary language used at Amazon.  The first thing I did was investigate what functional aspects have been added to the language since I last used it, because I enjoy the functional nature of JavaScript.  In this tutorial, I’ll show you what I’ve learned so far.

Our Previous Example

To begin, let’s rewrite the Java example used in the previous post in order to show how Java has evolved to handle functions with Java 8.  Originally we had:


public static Integer addOne(Integer number){ 
    return number + 1; 
} 

public static Integer squareNumber(Integer number){ 
    return number * number; 
} 

public static Integer composeFunctions(Integer input){ 
    return addOne(squareNumber(input));
}

 

This can be rewritten functionally as:

public static Function<Integer,Integer> addOne = (Integer number) -> {
    return number + 1;
};

public static Function<Integer,Integer> squareNumber = (Integer number) -> {
    return number*number;
};

public static Integer composeFunctions(Function f1, Function f2, Integer input){
    return (Integer)f2.apply(f1.apply(input));
}

 

You’ll notice a few peculiarities that don’t match up with the JavaScript example.  The first is the lambda functions.  In the case of our JavaScript example, we were able to assign our functions to variables:


var fun = function(){
    console.log("I'm a function!");
}

 

wp-1462347730081

(anyone? anyone? alright…sorry back to the code….)

However, we can use a slick bit of syntax named the “fat-arrow function” to write this another way:


var fun =  () => {
    console.log("I'm a Star Wars");
}

 

That’s all this is in the Java code, but they’re called “lambda functions” and they use -> instead of =>.  Obviously there are going to be some differences in the details, but for our purposes, you can view them as the same. (note, they’re also called anonymous functions)

A second peculiarity you’ll notice is the Function<Integer,Integer> variable type.  This is Java’s way of overcoming the “functions can’t be variables” we talked about in the previous post.  This variable is a Function variable (just like Integer, or String).  The syntax is a throwback to the OG functional programming languages as they define their functions similarly.  What it’s saying is “this is a function that receives an Integer type and returns an Integer type”.

This allows Java to do things like have functions which take Integers and return functions that take Integers and return Integers (Function<Integer,Function<Integer,Integer>>), or functions that take functions and return functions that take Integers and return Integers (Function<Function<Integer,Integer>,Integer>> I could go on for days, here simultaneously having a bit of fun, as well as foreshadowing for my frustrations with the Java language below).

Yet another peculiarity is this .apply() business.  JavaScript has this as well, and honestly I haven’t looked into the difference between .apply() and simply calling the function in JavaScript, although I’m certain there is a difference.  But anyway, that’s all that’s happening here.  f1.apply(input) is calling our first function with the input, this is returning an Integer, which is passed into f1.apply(), thus calling f1, and, finally, we return the result when the f1.apply() call finishes.

The final peculiarity is, the .apply() method returns an object.  We need to cast this object to an Integer which should be safe enough given we can see the function we’re passing in returns an Integer, however, it would pay to be extra safe about this if you were writing any kind of serious code, especially because the parameter is simply a Function, and not a Function<Integer,Integer> specifically.

In the previous post I pointed out that JavaScript is a mess of a language.  Here we see one of the differences between JavaScript and Java, and that’s static typing (I’ve heard this joked about as “JavaScript: everything is everything!”).  Here we are explicitly defining that the first two parameters passed into our composeFunctions method must be functions (ok, I’ll admit, bad naming).  In the case of the equivalent JavaScript code, we could very easily pass in an object in place of the function and we won’t get an error until run time, this can lead to some nasty bugs, and a severe lack of readability when looking at other people’s code.  But I digress, onto the next example!

First Class Functions In Java

public static void testFunction(String name){

    Runnable innerFunction = () -> {
        System.out.printf("hello! ");
    };

    BiConsumer<Runnable, String> lateExecution = (Runnable inputFunction, String n) -> {
        inputFunction.run();
        System.out.println(name);
    };

    BiConsumer<Runnable, String> lateNoExecution = (Runnable inputFunction, String n) -> {
        System.out.println(name);
    };

    lateExecution.accept(innerFunction, name);

    lateNoExecution.accept(innerFunction,name);

}

We previously discussed the issues with JavaScript, so now let’s bitch about Java.  In the equivalent JavaScript code from the previous post it was extremely succinct and easy to follow what was going on.  We were defining some inner functions, assigning them to variables and calling them.  The code is literally running off the page in this Java example. In this Java case, you have to know what a Runnable is, and that it’s an functional interface (whatever that is) that takes no parameters and returns none.  You also need to know that a BiConsumer takes two parameters specifically, and returns nothing.  Don’t you dare try using the Function interface for either of these things.  Don’t think about calling apply() on the BiConsumer either.

The equivalent JavaScript took me 1 minute to write and didn’t involve any googling or a compiler to double check.  Sadly, I can’t say the same for the Java.  Obviously the functional aspects of Java were an afterthought (which is fine, it wasn’t intended for that purpose anyway), and you get that feeling when trying to program functionally in it.

Remember in the previous post when I asserted that functional languages are great because the modularity is natural to a programmer, making it more probable to occur?  When you have to memorize 10 different functional interfaces to get anything done, that reduction in cognitive load vanishes.

In the next post I’m thinking we’ll look further into lambda functions, as well as the .map(), .filter(), and .reduce() higher order functions (used in the famous Hadoop big data framework).  Until then!

 

The Power of Functional Programming (and why we’ll be exploring it in Java)

I dislike Java as a programming language.

I learned C++ at Utah State University (not that I like C++ any better), we were required to take a Java course to supplement the C++ knowledge, but I had studied Java in my free time before going back to school anyway.  I am grateful to Java as it was my first experience with Object Oriented Programming (OOP).  C++ is less verbose than Java, but I don’t necessarily love C++ more than Java.  In all honesty, I’m not much of a language snob.  I’m firmly in the “choose the language that’s best for the job” camp.  Which is why I haven’t complained about using Java.  It really is the right tool for what Amazon is doing.

This is why after school I focused heavily on learning JavaScript.  In my opinion JavaScript is an absolute mess of a language, however, in many cases, particularly the projects I’m interested in building, it is the best tool for the job.  One thing in particular I like about programming in JavaScript is it’s functional aspects.  I’m not one for details or pedantry, so I’ll stay out of defining functional programming or using any programming language buzz words.  Here is the wikipedia to Functional Programming though, and if there is interest, I’d be more than happy to dive into other details of functional programming not discussed here (we’ll only be covering a very small subset).  For now, I’ll take a very simple definition of functional programming: functions can be treated as variables in functional languages, as this is the most advantageous aspect the paradigm possesses over procedural languages (C++, Java, etc).

I remember when I first heard of functional programming.  I thought “great, so what? I can accomplish anything I need to in a procedural language, why bother learning another paradigm and confusing myself?”.  In fact, although I’d dabbled in Haskell, this was more out of curiosity about all the hype surrounding functional programming than anything else.  It was really certain frameworks in JavaScript (looking at you React.js) that naturally lend themselves to the functional paradigm that introduced me in a pragmatic way.

Higher Order Functions

So functions can be treated as variables, what does this really mean?  Here’s a contrived example to illustrate the point:


var addOne = function(number){
    return number + 1;
};

var squareNumber = function(number){
    return number * number;
}

var composeFunctions = function(func1, func2, input){
    return func2(func1(input));
};

Calling composeFunctions(squareNumber, addOne, 100) will square 100, pass the result into addOne, and add 1 to 10000.  Here’s the equivalent Java code:


public static Integer addOne(Integer number){
    return number + 1;
}

public static Integer squareNumber(Integer number){
    return number*number;
}

public static Integer composeFunctions(Integer input){
    return addOne(squareNumber(input));
}

If you’ve studied functional programming in any small sense, you’ll be able to spot a limitation with this Java code (hint: notice how in the JavaScript we’ve got three function parameters to composeFunctions, but only 1 in the Java code).  What happens if we want the ability to call the addOne function first, and then the squareNumber function after that?  We’d have to add a second Java method for this and explicitly call these functions in the reverse order:


public static Integer composeFunctionsReverse(Integer input){
    return squareNumber(addOne(input));
}

This is because in the past, Java couldn’t treat functions as variables, and because of this, you can’t pass a function into another function as a parameter.  In the case of the JavaScript, if we wanted to change the order the functions executed in, it’s as simple as swapping the parameters to the function (calling composeFunctions(addOne, squareNumber, 100) instead of composeFunctions(squareNumber, addOne, 100)).

I remember when I was looking into functional programming initially, I saw examples like this and thought “great, so what? I’ll just write another one line function, what’s the big deal?”.  I’ll admit, in this contrived example it doesn’t seem like much.  However, when you start adding things like networking code to make API calls, or threading, the power of this small abstraction becomes enormous.  Not to mention the cleanliness of the code (we didn’t have to write the second function in the JavaScript case).

First Class Functions

Another powerful aspect of this paradigm is, the functions can be written inside of other functions, and executed whenever the programmer dictates:


var testFunction = function(name){
    var innerFunction = function(){
        //ignore the process.stdout.write, it's just console.log
        //without the newline
        process.stdout.write("hello! ");
    };

    var lateExecution = function(inputFunction, name){
        inputFunction() + console.log(name);
    }

    var lateNoExecution = function(inputFunction, name){
        inputFunction + console.log(name);
    }

    lateExecution(innerFunction, name);
    lateNoExecution(innerFunction, name);
}

Here is yet another contrived example, however, it illustrates the point quite well, particularly because there is no equivalent Java code to do the same thing (until recently of course, check out the next tutorial for this).

When we call testFunction(“Jackson”), the innerFunction is created at the time of calling, we then pass this variable into both our lateExecution and lateNoExecution variables (also both created at the time of calling testFunction).  The lateExecution function receives this innerFunction, immediately calls it, then console.log’s the name passed into it.  However, in lateNoExecution, we don’t ever execute the function passed to us, so nothing happens, other than “Jackson” is printed to the screen, even though we still have access to the function as a variable.

I know if you’ve come from procedural programming, you’ll read the above paragraph and thinking “man, that’s a lot of this calling that, calling this, but maybe not calling that, and only when the function is executed”.  I know because I thought the same thing.  But now that I’m on the other side of the fence I’m realizing the writers of posts I’d read previously were simply struggling to come up with succinct examples motivating the paradigm.  It just isn’t easy to motivate functional programming in small examples.  The paradigm really shines when code starts to grow very large, because functions can be chosen or removed at will and modularized with one simple key stroke rather than redesigning the software from the ground up (looking at you class hierarchy diagrams).

As an example, in the composeFunctions portion of this post, what would happen if we needed to do some preprocessing on the number passed into us before calling the other two functions, based on whether the number was even or odd?  We’d do the check on the number, and add the preprocessing.  Well next month, a customer has decided the preprocessing needs to be done in another way.  Between now and then, we’ve added a bit more logic in that if statement block.  Now we need to unravel the entire mess and change whatever preprocessing we were doing, which may effect logic (aka mutate state) later in the scope without us noticing.  If we were using functional programming, we’d have simply added a third preprocessing function as a parameter to composeFunctions, and called it inside the if statement.  When the customer changes the preprocessing requirements, we simply pass in the new function.

Another possbility: what if we wanted to reuse this composeFunctions method for a succession of two different function calls, rather than squareNumber and addOne?  (perhaps cubeNumber and addTwo?) without removing the functionality gained from the original code?  In Java you’d have to write a new function, calling cubeNumber and addTwo specifically, whereas here, we need only call composeFunctions with the newly written cubeNumber and addTwo (or hell, even cubeNumber and addOne, or addOne and addTwo).

This paradigm lends itself to modularity in a way procedural programming does not.  I’m not saying you couldn’t accomplish the same things in a procedural language, but what I am saying is, it’s much easier to do in a functional language, making a programmer much more apt to reach for it.

Hopefully I’ve managed to motivated the power of functional programming (although after reading the above paragraphs, I’m not sure sure I have! ha ha!).  This is a very small piece of the larger paradigm, and in fact, the power isn’t done justice by these contrived examples, the power lies in the completely new way of looking at code, rather than specific use cases or academic ammunition for water cooler arguments over which language is better.  As we’ll see in the tutorial, even traditionally procedural languages are adding functional aspects because of it’s power.