Is Java 8 a Functional Programming Language?

A surprising observation

I’m pretty excited about Java 8 most important feature: lambda expressions. I can think of so many ways to utilize them I can hardly wait until I can use Java 8 in vocational life. Lambdas stem from the world of functional programming languages, so obviously Java 8 is a functional programming language. It’s in the same league as languages like LISP, Clojure and Scala.

But wait – is this true?

Some ten months ago I used Java 8 to write a Mandelbrot set plotter. No matter how hard I tried, the program wouldn’t become functional. It was just a good old procedural program using a couple of lambda expressions. It can’t be the algorithms fault: Mandelbrot sets are all about functions. So what is it that stops Java 8 from being a functional language?

Effectively final: closing over values instead of variables

Project Lambda’s decision to dismiss full-blown closures has been criticized a lot. To avoid confusion and disappointment the team members call their closures lambda expressions. Most people expect closures to be able to modify variables defined outside the closure. A closures variable scope “closes over”1. the scope the closure is defined in.

Java 8 lambda expressions can access variables of the outer scope if they are final. Lambdas don’t close over variables, they close over values. This definition allowed Project Lambda to slightly loosen the requirements: lambdas are allowed to use outer scope variables if they are not formally declared final. It suffices to ensure they are not changed (they are “effectively final”).

Is Java 8’s failing to be a functional language something to do with the lack of full-blown closures?

No. Quite the contrary. No doubt about it, full-blown closures add a lot of value to a language (plus a bunch of problems, by the way), but they don’t make a language functional. Full-blown closures can even be considered an obstacle on the way to a functional language. Functional programming isn’t about variables. It’s about functions. Most functional programming languages don’t encourage the use of variables. For instance, many Scala programs do almost without variables. Scala programmers typically prefer “val” over “var”. It may sound weird to seasoned programmers of Java, Visual Basic, C/C++ or any other of the tradtional languages, but it is perfectly possible to write programs lacking variables. In fact, there are even languages like LISP that don’t know the concept of a variable.

Truth to tell there are languages that do need variables. It’s utterly impossible to write an assembler program without the ability to change memory cells (which can be considered a predecessor of variables). The same applies to pre-object-oriented BASIC and to non-OO Turbo Pascal. However, it should be possible to abstain from using variables with most object-oriented languages including Java.

Range types are missing in Java 8

The one feature preventing my Mandelbrot set program to be functional was Java 8’s lack of range types.

Drawing a Mandelbrot set amount to repeating the same algorithm for every pixel of the window. Basically the algorithm looks like so:

for (int x = 0; x < window.width; x++) {
    for (int y = 0; y < window.height; y++) {
        if (mandelbrotFormulaConvergesAt(x, y)) {
            drawPixel(window, x, y);
        }
    }
}

Groovy programmers can convert this algorithm to a more functional style by using range types:

<sup class='footnote'><a href='#fn-1561-2' id='fnref-1561-2' onclick='return fdfootnote_show(1561)'>2</a></sup> { x -&gt;
    <sup class='footnote'><a href='#fn-1561-3' id='fnref-1561-3' onclick='return fdfootnote_show(1561)'>3</a></sup> { y -&gt;
        if (mandelbrotFormulaConvergesAt(x, y)) {
            drawPixel(window, x, y);
        }
    }
}

Unfortunately, there is no nice equivalent to 4 or the even shorter version 1024.times{....} in Java 8. At first glance this doesn’t seem to be important. But the principal motivation to introduce lambda expressions to Java was to support massively parallel computing. The nice thing about 1024.times{...} is you don’t specify the order of the closure invocations. All you know is the closure is executed 1024 times. It can be invoked in any order – including invoking it simultaneously, 1024 calls in parallel.

Java 8 simply doesn’t allow for a really concise equivalent of 1024.times{...}. Sooner or later a library will fill the gap. Maybe it’ll look like this:

class RangeUtils {
  static void times(int repetitions, Closure t)
  {
    for (int i = 0; i < repetitions; i++)
       invoke(t(i));
    }
  }
}

Even so, Java 8 is going to remain a more clumsy than its Groovy counterpart. The Mandelbrot example looked like that:

RangeUtils.times(window.width, {x ->
    RangeUtils.times(window.height, {y ->
        if (mandelbrotFormulaConvergesAt(x, y)) {
            drawPixel(window, x, y);
        }
    }
}

But it’s getting worse.

Lambda expressions are not first class citizens

I’ve been complaining about the verbosity of the times function I depicted above, but truth to tell it doesn’t look that bad. The real problem is you simply can’t define it in Java 8.

There is no generic closure type. Closures aren’t first class citizens in Java 8.

Java 8 lambda expressions are always mapped to interfaces. Lambda expressions are implemented as SAMs: Classes implementing a single abstract method. So you have to define the times method many times. You need an implementation for each combination of parameters and return types.

Java 8 tries to address the problem by introducing an impressive variety of generic predicate and consumer methods. Chances are you’ll never need a predicate method other than the predefined Java 8 methods. However, you need an infinite number of methods to cover every possible case – an impossible task.

Making lambda expressions first class citizens would solve the problem. However, this introduces a lot of new problems, so maybe it was a wise decision to leave the advanced features to the new kids in town. Scala, Closure, Groovy and many other JVM languages already cover this feature, so why should Java give up the advantage its remaining feature: being a blazingly fast language?

Currying

Granted, I doubt currying is used a lot in real-world business applications. Currying is important because it demonstrates an important concept of functional programming, and it shows whether a language can be called functional or not. Languages without currying aren’t functional.

As it turns out, Java 8 is functional by that measure. You can do currying. It doesn’t even look bad, as the example from StackOverflow shows:

public class CurryingAndPartialFunctionApplication
{
   public static void main(String[] args)
   {
      IntBinaryOperator simpleAdd = (a, b) -> a + b;
      IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;

      // Demonstrating simple add:
      out.println(simpleAdd.applyAsInt(4, 5));

      // Demonstrating curried add:
      out.println(curriedAdd.apply(4).applyAsInt(5));

      // Curried version lets you perform partial application:
      IntUnaryOperator adder5 = curriedAdd.apply(5);
      out.println(adder5.applyAsInt(4));
      out.println(adder5.applyAsInt(6));
   }
}

Update Jan, 29 2014: Currying in Java 7

A reader pointed out that my original example on currying does not show Java 8, but Java 7. Little wonder I found it ugly! In hindsight, I have to correct myself: functional programming in Java 7 deserves my respect. The language wasn’t made for this, so it’s a lot of boiler-plate code. For the sake of completeness, I add the Java 7 code example I found at Stackoverflow.com:

interface Function1<A, B> {
  public B apply(final A a);
}

interface Function2<A, B, C> {
  public C apply(final A a, final B b);
}

class Main {
  public static Function2<Integer, Integer, Integer> simpleAdd = 
    new Function2<Integer, Integer, Integer>() {
      public Integer apply(final Integer a, final Integer b) {
        return a + b;
      }
    };  

  public static Function1<Integer, Function1<Integer, Integer>> curriedAdd = 
    new Function1<Integer, Function1<Integer, Integer>>() {
      public Function1<Integer, Integer> apply(final Integer a) {
        return new Function1<Integer, Integer>() {
          public Integer apply(final Integer b) {
            return a + b;
          }
        };
      }
    };

  public static void main(String[] args) {
    // Demonstrating simple `add`
    System.out.println(simpleAdd.apply(4, 5));

    // Demonstrating curried `add`
    System.out.println(curriedAdd.apply(4).apply(5));

    // Curried version lets you perform partial application 
    // as demonstrated below.
    Function1<Integer, Integer> adder5 = curriedAdd.apply(5);
    System.out.println(adder5.apply(4));
    System.out.println(adder5.apply(6));
  }
}

As you can see, functional programming has always been possible in Java, but Java 8 is clearly an improvement. But still, it’s a far cry from functional programming in Groovy.

Lack of syntactical sugar

While not strictly necessary adding some syntactical sugar might make it a lot more attractive to use Java 8 in a functional way. Apart from the range types I think of short notations of arrays and hash tables:

List<String> trafficLight = ["green", "yellow", "red"];
HashMap<int, String> votes = ["tories": 55, "labour party": 45];

This would enable Java programmers to write lines like

["green", "yellow", "red"].println("Traffic light is %it.");

Doing the same in Java 8 requires quite a few lines, and there’s no advantage of functional programming style over procedural programming style. Both require roughly the same number of lines because of the boiler plate code. So many programmers will likely stick to what the procedural style they’re used to.

List<String> lights = new ArrayList<>();
lights.add("green");
lights.add("yellow");
light.ad("red");
for (String it in lights) {
    System.out.println("Traffic light is " + it + ".");
}
lights.stream().each( String it ->
    System.out.println("Traffic light is " + it + ".");
}

The stream function

A minor annoyance is the decision to introduce the stream and parallelStream functions instead of adding the functional API to every collection. Granted, introducing these two functions makes interface design a lot simpler because you only have to add just two methods to every collection (instead of several dozen methods otherwise). But having to write ".stream()" adds to the verbosity of the Java language, thereby undermining the idea of using lambda expressions to make the language more concise.

Conclusion

Functional programming has been possible in Java since the introduction of anonymous inner classes. However, anonymous inner classes require so much boiler plate code that the only example of functional programming in Java 7 is the Arrays.sort function. Maybe you can also include the event listeners of Swing and SWT. In most other areas anonymous inner functions are used very reluctantly by most programmers I know. I’m afraid the story is going to repeat again.

The introduction of lambdas will make the Java language a lot more expressive. I’m pretty sure lambda are going to be used a lot more than anonymous inner classes (albeit they are basically the same). But still, the Java language falls short of becoming a functional language. It’s almost possible to program Java 8 in a functional way. But there are enough rough edges making it difficult to do so. It bet Java will largely remain a procedural language.


  1. “Close over something” is scientific math jargon and means to “include”, “extends” or “contain something”
  2. .window.width-1
  3. .window.height-1
  4. .1023

18 thoughts on “Is Java 8 a Functional Programming Language?

  1. Pingback: Is Java 8 a Functional Programming Language? | ...

    1. Stephan Rauh Post author

      Yes, at least to a certain extent. I didn’t know IntStream.range(from, to) at the time of writing, so I chose a really weird solution. However, Java could benefit a lot from a little syntactical sugar. You know, a short line like

      1024.times{println(it);}

      looks a lot nicer than

      IntStream(0, 1024)({i -> System.out.println(i);})

      . I believe brevity is very important when it comes to functional programming: Lambda expressions need to be short and concise to be more expressive than procedural programming.

      Reply
  2. Martin

    Currying in Java 8:

          IntFunction curriedAdd = a -> b -> a + b;
          IntUnaryOperator adder5 = curriedAdd.apply(5);
          out.println(adder5.applyAsInt(4));
          out.println(adder5.applyAsInt(6));
    

    Looping arrays:

          Arrays.asList("a", "b").forEach(s -> print(s));
    

    No?

    Reply
    1. Stephan Rauh Post author

      Not quite. In fact, both examples illustrate my point. Yes, both examples are functional programming, and it’s also true the first example matches the definition of currying.

      But both examples are clumsy. Granted, the asList() example is short enough to be found in the wild, even though it’s not as concise as

      ["a", "b"].forEach(s -> print(s))
      

      It almost feels natural to use such a construction. Your currying example does not. It requires two special types (IntFunction, IntUnaryOperator) and it requires a call to the apply() method.

      My bet is Java programmers will avoid functional constructions if they are clumsy. Of course, every programmer has her / his own definition of clumsiness. Some will accept adder.applyAsInt(4), other will insist on simply writing adder5(4). By the way, your choice of names is instructive: adder is a noun. As a rule of thumb method and function names tend to be verbs.

      That said, I’d like to add it’s good you keep contradicting me. It makes me re-think the topic, and I guess readers benefit from the discussion, too. Thank you!

      Reply
  3. Pingback: Top 10 Very Very VERY Important Topics to Discuss | Java, SQL and jOOQ.

  4. Pingback: 10 things developers need to shut up about - JAXenter

  5. nnull

    In your conclusion, it points out the problem many people face when discussing this topic, including you also having the problem.

    Who care it’s functional or not, if it can’t be done nicely, and solve the problem nicely.

    So I suggest all these people stop thinking about when it meets the functional definition. They should look at the problems, and how it solves it.

    I agree with the language not providing anonymous/generic interface, versus people having to declare each interface, unless declared.

    In fact, a class should not need to implement an interface at all for a function to be passed around. If a class’s method has the right signature, it should be passed to a a function requiring that signature. That is why JS has this advantage over Java. You can pass any function pointer as another parameter, and people just call/apply/() that, and it works. Reduce alot of things. The nice thing about supporting this in Java is that it would work with compile time checking, because all the parameters and return type are matched up, that’s all it’s needed. No need for interface.

    Some other examples you provided, I don’t know if one is better than the other, it’s all down to preferences.

    Reply
    1. Stephan Rauh Post author

      One thing’s for sure: Java 8 is a major improvement over Java 7. Passing functions or methods as parameters is a big ticket. I’ve been missing this features for years. And yes, Lambda helps us to solve our customers’ problems.

      However, many functional programmers report the functional programming style allows them to solve many problems better, more efficiently, with less errors and so on. When I wrote the article I was disappointed because I couldn’t adopt such a functional programming style in Java 8. The pure (or puristic?) functional approach is a different set of mind. You can do without variables. This alone is a game-changer. Among other things, it make multi-threading very simple. From this point of view it’s a pity Java 8 discourages a pure functional style.

      I suppose things will become slightly better in Java 9 and beyond, but the imperative programming style is a integral part of the spirit of both the Java language and the average Java programmer, so I don’t expect too much change.

      Reply
  6. Reader

    I am both neutral and a neophyte on this topic, but thought it important to report what appears to be an error in the article:

    Under the “Currying” section you link to a Stack Overflow post for Java 7 (written in May of 2011- before Java 8). http://stackoverflow.com/a/6134321. This unequivocally ugly code should not be introduced to readers of the article as Java 8 as it does not and could not contain Java 8 constructs.

    This post demonstrates the ugliness of imitating Currying in Java 7 and has no bearing on Java 8’s capabilities.

    A correct (and rather concise) example of Currying in Java 8 is here: http://stackoverflow.com/a/14750362

    Reply
      1. Stephan Rauh Post author

        I corrected the article. You’re right, I was mistaken – thanks for pointing this out!

        BTW, I fixed the minor formatting issue you mentioned in your follow-up post. No problem.

        Reply
  7. Pingback: Java 8 – on the path to improving developer sanity | Shine Technologies

  8. Daniel Dietrich

    Hi,

    I’ve also learned from other languages like Scala and Haskell that there are two key factors to get the most out of a language – well designed collections and control structures. Some things we are not able to emulate in Java, like for-comprehensions, pattern matching and a more mature type system (higher-kinded types). Having expressions instead of statements is also helpful but not possible in Java.

    But there are things we might do – like designing a new, immutable collection library and providing additional (monadic) control structures, leveraging lamdas. I’m doing this with Javaslang, a functional component library for Java 8+. Here is an overview of the upcoming release 1.3.0 in one picture.

    Reply
  9. vincent

    It is simply factually incorrect to say that LISP (which is archaic in itself and doesn’t refer to any particular language) lacks variables. Essentially every lisp (except Clojure) treats bindings as variable by default and many do not have a native concept of an invariant bindings. Eg, in Common Lisp/Emacs Lisp:

    (let ((x 10)) (setq x 11))

    Is valid code and modifies the value of x.
    With the exception of Clojure, most Lisp dialects are only slightly functional: they support first class functions but values are not immutable.

    Reply
    1. Stephan Rauh Post author

      Hm, you seem to be right. I remember having done some research on this, but I seem to have seen the wrong references. Is there a programming language without variables out there? I’m sure you don’t need variables, but they are so useful, so even Forth knows variables. Even machine code knows a similar concept, too: storing values into certain memory cells is equivalent to defining and using variables.

      Reply

Leave a Reply

Your email address will not be published.