EmailLinkedInGoogle+TwitterFacebook

The parts of this post discussing Lambda expressions might not be exact to the current specification syntax under discussion.  Neither are these featured present in currently released JDKs (upto JDK7).  So it is not compilable.  Look at it only as pseudo code to discuss general notions around Lambda expressions in Java.

One of the key feature additions much expected in JDK7 was language level support for closures using lambda expressions. The spec’s initial release was disturbing for regular java programmers including me because it resembled less of the java anyone wrote.  For example:

   String reply = { -> "Hello World" }.invoke();
   System.out.println(answer);

is an inline closure that creates a function that returns java.lang.String “Hello World” whenever it is invoke() ed.  Nice – does not look like java but is a handy tool.  For example, wouldn’t it be great if we could write a comparator inline?

		Person[] persons = new Person[] {new Person("Me",10,0.9f), new Person("You", 12, 0.8f)};
		Arrays.sort(persons, new Comparator<Person>() {
			public int compare(Person o1, Person o2) {
				if (o1.age > o2.age) return 1;
				else if (o1.age < o2.age) return -1;
				else return 0;
			};
		});

could rather be written as

		Person[] persons = new Person[] {new Person("Me",10,0.9f), new Person("You", 12, 0.8f)};
		Arrays.sort(persons,{Person a, Person b -> (a.age < b.age) ? 1 : (a.age > b.age ? -1 : 0)});

a wee bit condensed code but much too cryptic. I would still take it since for some trivial places I could avoid creating a class where all I needed was a function.  Further more closures or these anonymous functions are first class citizens of jvm whom I can assign to a variable and pass around.  So, for example I could have very well written the code above as follows.

		Person[] persons = new Person[] {new Person("Me",10,0.9f), new Person("You", 12, 0.8f)};
		final function f = {Person a, Person b -> (a.age < b.age) ? 1 : (a.age > b.age ? -1 : 0)};
		Arrays.sort(persons,f);

The following quote from the JSR preface explains what the closures in Java thrived to achieve.  Past tense is intentional because closures where dropped from JDk7 and I have little hope that it is going to be a language addition in JDK8.

‘This JSR provides support for operating on an arbitrary “block of Java code”, or body, which is either a statement list, an expression, or a combination of both. We call the mechanism a closure expression. Wrapping statements or an expression in a closure expression does not change their meaning, but merely defers their execution. Evaluating a closure expression produces a closure object. The closure object can later be invoked, which results in execution of the body, yielding the value of the expression (if one was present) to the invoker. A closure expression can have parameters, which act as variables whose scope is the body. In this case the invoker of the closure object must provide compatible arguments, which become the values for the parameters.’

That being said, let us look at what is it that we are missing in Java because there is no language level support for closures.  I don’t see many.  Java from the ground up resembled a good boy.  It encouraged cleaner coding and conventions that I seldom see broken – be it variable naming, comment blocks or standard use of available libraries to not to reinvent the wheel.  For a long time it was touted as a tortoise (compared to snappy C++ compiled natives) but not any more – thanks to faster multi core processors.  Now to that mix the proposal adds lambda expressions a cryptic clunk to achieve just the same things that can be achieved with anonymous inner classes.  Language level closure support is cool and I would embrace it whole heartedly.  But not this lambda based implementation.  Let me rest my case by demonstrating how easy it is to code functions as variable and pass it around with current Java constructs.  There are pitfalls and there is a need for more code.  But more code does not always mean more execution blocks.  So, My vote is to drop the lambda expressions based closures from Java language.

	abstract class Function<O, I> {
		protected abstract O function(I inputParameter);

		public final O invoke(I inputParameter) {
			return function(inputParameter);
		}
	}

	class TestClass {
		public Function<String, Object> getRandomString = new Function<String, Object>() {
			@Override
			protected String function(Object inputParameter) {
				return UUID.randomUUID().toString();
			}
		};
	}

	@Test
	public void testClosure() {
		TestClass myTestClass = new TestClass();
		System.out.println("TestClass before mutation :"
				+ myTestClass.getRandomString.invoke(null));
		myTestClass.getRandomString = new Function<String, Object>() {
			@Override
			protected String function(Object inputParameter) {
				return UUID.randomUUID().toString()
						+ UUID.randomUUID().toString();
			}
		};
		System.out.println("TestClass after mutation :"
				+ myTestClass.getRandomString.invoke(null));
	}

More information on java closures are available from these resources

http://www.javac.info/consensus-closures-jsr.html

http://tronicek.blogspot.com/2007/12/java-closures-tutorial.html

http://openjdk.java.net/projects/lambda/

http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html

One Thought on “Java does not have closures – or has it?

  1. Anonymous on October 17, 2012 at 9:43 pm said:

    Your original code is unnecessarily complex. That’s why the lambda code is cryptic. This is how you should have written your comparator:

    new Comparator() {
    public int compare(Person o1, Person o2) {
    return o1.age – o2.age;
    }
    }

    So this is how you should have written your sorting lambda:

    Arrays.sort(persons,(p1,p2) -> p1.age – p2.age);

    If you’d used an array it would have been even shorter:
    persons.sort((p1,p2) -> p1.age – p2.age);

    If you have a genuinely complex comparation method either use a comparator just like before (nothing wrong with that) or take advantage of the new method handles feature:

    // Comparator (traditional)
    persons.sort(PersonComparators.SORT_BY_FOO);

    // Method handles (new syntax)
    persons.sort(PersonComparators::sortByFoo);

    Lambdas will make code much clearer by eliminating a lot of boilerplate code in favour of the actual logic. But if the actual logic is poorly thought out they can’t help.

    Luckily your “vote” counts for nothing.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Post Navigation