Java is an old language and there are many new kids on the block who are challenging it on its own terrain (the JVM). However, Java 8 arrived and brought a couple of interesting features. Those interesting features enabled the possibility of writing new amazing frameworks like the Spark web framework or Javaslang.

In this post we take a look at Javaslang which brings functional programming to Java.

Functional Programming: What is it Good For?

It seems that all the cool developers want to do some functional programming nowadays. They wanted to use object-oriented programming before. I personally think functional programming is great to tackle a certain set of problems, while other paradigms are better in other cases.

Functional programming is great when:

you can pair it with immutability: a pure function has no side-effect and it is easier to reason about. Pure functions means immutability, which drastically simplifies testing and debugging. However not all solutions are nicely solved with immutability. Sometimes you just have a huge piece of data shared between several users and you want to change it in place. Mutability is the way to go in that case.

you have code which depends on inputs, not on state: if something depends on state instead of input it sounds more like a method that a function to me. Functional code ideally should explicitly say which information is being used (so it should use just parameters). That also means more generic and reusable functions.

you have independent logic, which is not highly coupled: functional code is great when it is organized in small, generic and reusable functions.

you have streams of data that you want to transform: this is in my opinion the easiest place where you can see the values of functional programming. Streams received a lot of attention in Java 8.

Javaslang™ is the missing part and the best solution to write comprehensive functional Java 8+ programs.

This is exactly how I see Javaslang: Java 8 gave us the enabling features to build more concise and composable code. But it did not do the last step. It opened a space and Javaslang arrived to fill it.

Javaslang brings many features to the table:

currying: currying is the partial application of functions

pattern matching: think of it as the dynamic dispatching for functional programming

failure handling: because exceptions are bad for function compositions

Either: this is another structure which is very common in functional programming. The typical example is a function which returns a value when things go well and an error message when things don't

tuples: tuples are nice lightweight alternatives to objects and perfect to return multiple values. Just do not be lazy and use classes when it makes sense to do so

memoization: this is caching for functions

For developers with experience in functional programming this will all sound familiar. For the rest of us let’s take a look at how we can use this in practice.

OK, But in Practice How Can We Use This Stuff?

Obviously showing an example for each of the feature of Javaslang is far beyond the scope of this post. Let’s just see how we could use some of them and in particular let’s focus on the bread and butter of functional programming: functions manipulation.

Given that I am obsessed with manipulation of Java code we are going to see how we can use Javaslang to examine the Abstract Syntax Tree (AST) of some Java code. The AST can be easily obtained using the beloved JavaParser.

We are going to implement very simple queries. Queries that can be answered just by looking at the AST without solving symbols. If you want to play with Java ASTs and solve symbols you may want to take a look at this project of mine: java-symbol-solver.

For example:

find classes with a method with a given name

find classes with a method with a given number of parameters

find classes with a given name

combining the previous queries

Let’s start with a function which given a CompilationUnit and a method name returns a List of TypeDeclarations defining a method with that name. For people who never used JavaParser: a CompilationUnit represents an entire Java file, possibly containing several TypeDeclarations. A TypeDeclaration can be a class, an interface, an enum or an annotation declaration.

getTypesWithThisMethod is very simple: we take all the types in the CompilationUnit (cu.getTypes()) and we filter them, selecting only the types which have a method with that name. The real work is done in hasMethodNamed.

In hasMethodNamed we start by creating a javaslang.collection.List from our java.util.List (List.ofAll(typeDeclaration.getMembers()). Then we consider that we are only interested in the MethodDeclarations: we are not interested in field declarations or other stuff contained in the type declaration. So we map each method declaration to either Option.of(true) if the name of the method matches the desidered methodName, or we map it toOption.of(false). Everything that is not a MethodDeclaration is mapped to Option.none().

So for example, if we are looking for a method name “foo” in a class which has three fields, followed by methods named “bar”, “foo” and “baz” we will get a list of:

The next step is to map both Option.none() andOption.of(false) to false and Option.of(true) to true. Note that we could have done that immediately instead of having two maps operation concatenated. However I prefer to do things in steps. Once we get a list of true and false we need to derive one single value out of it, which should be true if the list contains at least one true, and false otherwise. Obtaining a single value from a list is called a reduce operation. There are different variants of this kind of operation: I will let you look into the details.

Why? It seems (and is) much more complicated but it shows us how we can manipulate functions, and this is an intermediate step to obtain code which is more flexible and powerful. So let’s try to understand what we are doing.

First a quick note: the class Function1 indicates a function taking one parameter. The first generic parameter is the type of the parameter accepted by the function, while the second one is the type of the value returned by the function. Function2 takes two parameters.

We:

reverse the order in which parameters can be passed to a function

we create a partially applied function: this is a function in which the first parameter is “fixed”

So we create our originalFunctionReversedAndCurriedAndAppliedToMethodName just by manipulating the original function hasMethodNamed. The original function took two parameters: a TypeDeclaration and the name of the method. Our elaborated function takes just a TypeDeclaration. It still returns a boolean.

We then simply transform our function in a predicate with this tiny function which we could reuse over and over:

/**
* Get all the types in a CompilationUnit which satisfies the given condition
*/
public List<TypeDeclaration> getTypes(CompilationUnit cu, Function1<TypeDeclaration, Boolean> condition) {
return List.ofAll(cu.getTypes()).filter(asPredicate(condition));
}
/**
* It returns a function which tells has if a given TypeDeclaration has a method with a given name.
*/
public Function1<TypeDeclaration, Boolean> hasMethodWithName(String methodName) {
Function2<TypeDeclaration, String, Boolean> originalFunction = AstExplorer::hasMethodNamed;
return originalFunction.reversed().curried().apply(methodName);
}
/**
* We could combine previous function to get this one and solve our original question.
*/
public List<TypeDeclaration> getTypesWithThisMethod(CompilationUnit cu, String methodName) {
return getTypes(cu, hasMethodWithName(methodName));
}

This is of course a very limited introduction to the potential of Javaslang. What I think is important to get for someone new to functional programming is the tendency to write very small functions which can be composed and manipulated to obtain very flexible and powerful code. Functional programming can seem obscure when we start using it but if you look at the tests we wrote I think they are rather clear and descriptive.

Functional Programming: Is All The Hype Justified?

I think there is a lot of interest in functional programming but if that becomes hype it could lead to poor design decisions. Think about when OOP was the new rising star: the Java designers forcing programmers to put every piece of code in a class and now we have utility classes with a bunch of static methods. In other words, we took functions and asked them to pretend to be a class to gain our OOP medal. Does it make sense? I do not think so. Perhaps it helped to be a bit extreme to strongly encourage people to learn OOP principles. That is why if you want to learn functional programming you may want to use functional-only languages like Haskell: because they really, really push you into functional programming so that you can learn the principles and use them when it makes sense to do so.

Conclusions

I think functional programming is a powerful tool and it can lead to very expressive code. It is not the right tool for every kind of problem, of course. It is unfortunate that Java 8 comes without proper support for functional programming patterns in the standard library. However some of the enabling features have been introduced in the language and Javaslang is making it possible to write great functional code right now. I think more libraries will come later, and perhaps they will help keeping Java alive and healthy for a little longer.