Geertjan is a DZone Zone Leader and has posted 458 posts at DZone. You can read more from them at their website. View Full User Profile

Closures Solution: Include Groovy in the JDK?

04.04.2008
| 14260 views |
  • submit to reddit
The closures debate often seems to consist of two separate discussions—first there's the discussion around how best a closure could be expressed in Java; secondly there is a discussion around a meta question: "Should the Java language change at all, regardless of the benefits of doing so?" Here I, hesitantly, point to a direction that might lead somewhere, even if only to further discussion...

Recently a poll was held on java.net, about which of the closure proposals respondents support. The results were as follows:

For the uninitiated, here's a short phrase guide:

-- BGGA ("full closures for Java"), the most full blown proposal, named after the first letter of its proposers' surnames, in other words, Gilad Bracha, Neal Gafter, James Gosling, and Peter von der Ahé.

-- CICE ("concise instance creation expressions"), proposed by Bob Lee, Doug Lea, and Josh Bloch.

-- FCM ("first class methods"), proposed by Stephen Colebourne and Stefan Schulz.

For completion's sake, there's also Bruce Chapman's interesting "No Closures" proposal, which has as an additional benefit that "you don't have to wait for JDK 7 to use it".

The discussions about syntax, flowing from the above proposals, point to interesting conclusions. In particular, Cedric Champeau wonders about Groovy's syntax and suggests that Java adopts the same for its closures-to-be. The question to ask, however, is how pertinent discussions about syntax ultimately will be, since whatever syntax is chosen, programmers will adopt it. Look at generics, for example. Pretty ugly, I believe, but it's been picked up and used since its adoption. But that's also my point—at some stage Java should not change anymore, right? At some point Java will have reached its maximum width and height and it would be crazy to continue stretching it beyond its intended shape. One might even suggest that generics was a bridge too far.

In that light, might the solution not "simply" (there is no "simply" here, of course) be this:

I don't believe the benefits Groovy has over all other scripting languages need to be argued again. In short, since Groovy is an implementation detail of Java, its natural cousin (and much else besides), why not make it available to the Java platform? Why continue stretching Java out of shape when Groovy offers exactly those kind of flexible constructs, such as closures, which Java is now trying to incorporate? Especially since we now have an OpenJDK? The question mystifies me and I am looking forward to responses to these thoughts.

Published at DZone with permission of its author, Geertjan Wielenga.

Comments

Mark Thornton replied on Sun, 2008/04/06 - 2:34am in response to: Ricky Clarkson

[quote=rickyclarkson] Simply untrue.  Common Lisp implementations are comparable in speed to Java and even outstrip C++ by a long way in certain areas (CL's conditions tend to work 100 times faster than C++'s exceptions, [/quote]

My understanding is while performance in general computing tasks is now good, there remain shortfalls in some areas of mathematical computation. I solve large scale combinatorial optimization problems.

Ricky Clarkson replied on Sun, 2008/04/06 - 5:54am in response to: Paul King

Fair enough, I should have used the word "promoters" instead of "creators".  None of the closure proposals add complexity to Java, as far as I can tell, any more than two people in two rooms is more complex than one person in one room.

The interaction between closures and other language features is fairly minimal, with the exception of checked exceptions, and even that has been solved with minimal change in BGGA.

My point was that it seems illogical to say that Groovy is Java plus closures, and in the same breath to say that adding closures to Java would be twisting it in wacky directions.

Paul King replied on Sun, 2008/04/06 - 7:52am in response to: Ricky Clarkson

[quote=rickyclarkson]

[...] None of the closure proposals add complexity to Java, as far as I can tell, any more than two people in two rooms is more complex than one person in one room. The interaction between closures and other language features is fairly minimal, with the exception of checked exceptions, and even that has been solved with minimal change in BGGA.[...]

[/quote]

In my opinion there is quite a lot of complexity there. When I give a Groovy course, I can usually find people get a good overview of Groovy Closures in under 60 mins. I can't imagine doing justice to BGGA in less than half a day. I am not saying that BGGA adds unneeded complexity if you want to cover all of the cases it is trying to handle, but there are a lot of aspects to worry about and not all of them will be hidden away from everyday Java programmers.

Also, I imagine there are still several hundred hours of thinking to go before the open issues for BGGA are resolved, so once that is done there will be more to cover. Once they are finished, if they stick to the current proposal, they will have a more powerful abstraction than Groovy's current Closures. I think Groovy's Closures even from Java will be simpler to explain and use, so that makes it interesting. On the other hand, the BGGA proposal does have some interesting features which Groovy currently doesn't handle yet, so it has some real strengths too despite the extra complexity.

Ricky Clarkson replied on Sun, 2008/04/06 - 10:13am

One reason Java closures might take longer to explain is that they are (explicitly) statically typed.  x => x+1 is visually simpler than int x => x+1.  Even if Java had type inference, it would probably not be possible to write something like:

var f={x => x+1}; and have it usable with any of the numeric primitive types (plus String), because there is no type that represents all of those.  It would take a better type system (better even than Scala's) to make static typing always look as good as dynamic typing.  Haskell has that, and probably OCaml too.

Groovy's closure types are pretty simple.. there's one, called Closure.  It takes no type parameters.  You cannot specify that a method takes a closure that has two parameters, let alone specify the types of those parameters.  Java's proposed closure types are syntax sugar for some VM-generated interfaces, much the same as its array types are - {int => int} looks like FunctionII after desugaring, and {int, int => int} looks like FunctionIII, and {Integer, Integer => Double} looks like FunctionOOO<Integer, Integer, Double> (where I means int and O means object).  I've already been using a language with similar syntax sugar, Scala, and apart from the special cases that Scala adds for other reasons (laziness), it seems pretty sane and consistent.  Scala's is a little simpler because there are no primitive types in Scala, so you only need Function1, Function2, etc., not different ones for primitive/reference types.

A lot of the open issues for BGGA have been solved already in other languages; it's largely a case of looking at existing solutions and seeing how they'd fit in Java.

Serge Bureau replied on Mon, 2008/04/07 - 11:55am in response to: Daniel Spiewak

Sorry but your attitude is pushing conservatism to the extreme.

Closures are a natural feature, it was in fact in SmallTalk from the start, it is a terrible omission in Java.

Groovy shows how easyly it can be used, and also how useful it is.

So it definitely has to make it to Java, in the meantime we do have Groovy.

 And I do want evolution in Java, not the starvation you promote.

Geertjan Wielenga replied on Mon, 2008/04/07 - 3:16pm

My concern is that closures, in each of the various variations presented thus far, are really complex. That's okay, even. However, each closure proposal is interpreted in different ways by different people. These complexities and ambiguities are not going to be doing Java any favors. If, every time a language comes up with a new structure or a new approach to doing something, Java responds by finding a way of replicating that functionality or approach... isn't there going to come a point where it, in addition to the problems of complexity and ambiguity, also will find itself simply being bloated? How far can we keep twisting Java in new directions?

This is not a case of advocating "starvation" of Java, as Serge, in the previous response, suggests. But an argument in favor of... simplicity. Let's let Java do what Java does. Let's not add layers of complexity. If you find Java limiting, if you really can't do without something that is found in another language, then USE that other language, whatever it is. Don't try to shoe horn their crown jewels into Java.

Now, the second element of my argument, which is separate from the above, is: Java has a young, modern, and hip cousin. Its name is Groovy. It does all the things that Java does, but it does them in a cooler way. It will never replace Java and no one is seriously arguing that it will. However, sometimes it would like to be around to lift Java up to the places where it can't reach. One of these places is closures. And, guess what? They can work perfectly together. You can mix and match Java at will. So, why not move Groovy into the house where Java has been living for so long? They'll be fine together and complement each other's strengths while helping to overcome each other's weaknesses. They're logical extensions of each other. Should you want flexibility and dynamic behavior... you'd have Groovy. Eventually, you'll have speed there too. (That's the next item on the Groovy team's wishlist.) Should you want heavy lifting and low level processing, you'd have Java.

Mark Thornton replied on Mon, 2008/04/07 - 3:34pm in response to: Geertjan Wielenga

[quote=geertjan] They'll be fine together and complement each other's strengths while helping to overcome each other's weaknesses. They're logical extensions of each other. Should you want flexibility and dynamic behavior... you'd have Groovy. Eventually, you'll have speed there too. (That's the next item on the Groovy team's wishlist.) Should you want heavy lifting and low level processing, you'd have Java. [/quote]

Where would this leave applications such as the use of closures with the fork join framework? Performance may be next on the Groovy team wish list, but they have a very long way to go to be an appropriate solution in the typical applications of fork join.

Adam Conover replied on Tue, 2008/04/08 - 12:06am in response to: Geertjan Wielenga

I've noticed a common theme in many of the posts here that adding features is synonymous with adding complexity. (Or that new features can only be added by subverting the existing design.) But the real questions in my mind are: "Where is that complexity being added?" and "Is complexity somewhere else being minimized?"

I think of a programming language like a tool box, ideally you could have a tool box for each catagory of task which requires different types of tools (working on a car vs. building cabinets). Adding a bunch of tools (language features) to the tool box (language) that are completely unrelated to the intended tasks would certainly add unnecessary complexity. Even adding new tools which are related to the intended task-type adds complexity in the sense that; now you must choose more carefully which tool is most appropriate and learn how to use the new tool in conjunction with the existing tools. However, just because you add complexity to the toolbox does not mean that any given job will automatically be more complicated. In fact, having a more complete toolbox generally makes complicated jobs much easier... once you master the tools.

I look at Java's existing strengths: reasonable cross platform support (lack of continuously up-to-date MacOS support is the biggest problem, IMO), vast API, great networking and threading capabilities, and static typing (which I strongly believe to be necessary for any large project involving multiple developers).... all of this makes Java a great "Software Engineering" language for large and/or complicated systems. I'm not saying that closures are essential to the survival of Java, but the question should be asked about whether it would make solving problems easier moving into the future. As the types of problems being solved evolve, the tools in the toolbox need to evolve too.

Geertjan Wielenga replied on Tue, 2008/04/08 - 12:22am in response to: Adam Conover

[quote=ajconover]

I'm not saying that closures are essential to the survival of Java, but the question should be asked about whether it would make solving problems easier moving into the future. As the types of problems being solved evolve, the tools in the toolbox need to evolve too.

[/quote]

I agree. But there are two ways in which tools in a toolbox can evolve. Let's take a handsaw as an example. You discover that your handsaw is not helpful when you want to chop down trees. You realize your tool needs to evolve. So, what do you do? Do you bolt the capabilities of a chainsaw onto your handsaw? No. You simply get a chainsaw in addition to your handsaw. You put them in the same toolbox and whenever you need to chop trees, you use your chainsaw, while for other work you continue using your handsaw.

Ricky Clarkson replied on Tue, 2008/04/08 - 9:45am in response to: Geertjan Wielenga

Geertjan said: "My concern is that closures, in each of the various variations presented thus far, are really complex."

Are the Groovy ones simpler?  Do you think that if Groovy was statically typed (so that closure types were more than just Closure) it would have something simpler than Java's?

I think "really complex" here is either propaganda or a misunderstanding.  While solving hardly any of the use cases for closures, CICE seems impossible to speak of as "really complex".  The others are hardly behemoths; perhaps the problem is the spec-speak involved.

"However, sometimes it [Groovy] would like to be around to lift Java up to the places where it can't reach. One of these places is closures".  Groovy lacks half the Java language (static typing), so it would be a case of giving up features to get others.  There is no reason why Java cannot gain closures.  If it didn't gel well, you'd have noticed because Groovy would have been a mess - Groovy is based on Java's grammar.

Michael Greifeneder replied on Tue, 2008/04/08 - 11:13am in response to: Artur Biesiadowski

I agree that Scala looks really promising. If you want to add functional programming, then do it like in Scala. Every function is an object, curryfication, high order functions and so on...

Mike P(Okidoky) replied on Tue, 2008/04/08 - 12:51pm

Groovy's performance is unacceptable.  Decompile a compiled script and see for youself (eg. run Jad on it).

Perhap the Groovy people desperately want to grab all the attention they can before Java gains enclosures.

Not too happy about how BGGA looks though... 

Raging Infernoz replied on Tue, 2008/04/15 - 3:14am

What is this stupidity?

How long do I have to wait to see very overdue features like proper generics, full closures and native continuations in Java. 

Please stop these nonsense hack ideas about abusing stupid scripting languages, just get these feature in Java already or I'll never be able to use them at work! 

Damn!

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.