I am a Java developer, designer, public speaker and a JAS 39 Gripen instructor fighter pilot. A somewhat unusual combination I guess, but I like challenges. I have created miglayout.com, migcalendar.com and Wing, a flight planning system used in several Air Forces. I find end user usability to be the most important part of a system and have therefore specialized in creating such applications. Mikael has posted 10 posts at DZone. View Full User Profile

Closures - Breaking the Deadlock

08.14.2008
| 10274 views |
  • submit to reddit
The decision threads about closures are currently in a situation that can best be described as a deadlock. BGGA has the most proponents, but also the biggest crowd against. FCS and CISE don't stir up too many anti-comments, but usually aren't the gurus' favorite proposal either since they lack new powers and doesn't represent the Java 3000 that many gurus want. This was the situation one year ago, and this is the situation today.

I do however think that we needsomethingfor Java 7. I'm pragmatic and think that Java will be nuked in the blogosphere if Java 7 comes with close to nothing exciting in the language department, even though it will have baked for as long as Tiger (summer 2009). Therefore, without further ado, I propose a two stage rocket for Java 7 and Java 8.

Stage 1

Lets ease up on the syntax and constraints for anonymous inner classes for Java 7. This should be done anyway since the number of anonymous inner classes will be much larger than actual closures in use for the foreseeable future.

Some snippets that illustrates what I mean, but any similar syntax will do as long as it is just an improvement of anonymous inner classes. No JVM changes and no "new" syntax. I can not stress this enough, the syntax is not what this article is about, the fact that stage 1 is easy to understand and easy to add to javac is. If you want more thought through syntax, think CICE without ARM and FCM without method pointers.

Interface with one method, no arguments:

SwingUtilities.invokeLater({
    System.out.println("Later, Man..");
});
Interface with one method, x number of arguments:
button.addActionListener({
actionPerformed(ActionEvent e) { e.doStuff();}
});

And the last improvement, which I think we are mature enough for now even though it was originally left out to keep complexity down. We need some way to use non-final local variables in an inner class:

volatile int myInt = 42; // Look, no final, and it IS editable...
SwingUtilities.invokeLater( { System.out.println("My int is now: " + myInt); } );

The use of volatile is something that I have thought about for a long time to solve the "final" problem. I just don't understand why it hasn't been added earlier to lift the restrictions on inner classes. It even makes it documented that the field is "volatile" and it has to do with threading, which is the original meaning on a field.

Stage 1 will add nothing new to the JVM, no "new" syntax and the old way will work. I think no one can really complain that this "isn't the Java way". IDEs that use javac for ASP processing will egen get this change for free.

Stage 2

Then, and only then, when we have tested this for a year or two in Java 7 can we really see how BGGA should be baked to get more power. Maybe we figure out that this is tasty and we need all the goods, or we think that we need only a little more power. Today this is only estimations. In two years at least we can say with certainty one way or the other.

The nice thing is that a closure proposal á la BGGA will not be hampered by this two stage rocket. It will probably not make it into Java 7 anyway because of time constraints and the current deadlock. Stage 1 is not competing and this rather small improvement of the language (since it is very easy to hack into javac) can be done in a speedy manner.

So, what do you think? Is this two stage rocket a sensible deadlock ejection? To me it sounds like the best approach and sort of a Middle Earth between Heaven and Hell (which one is wich is up to the reader to interpret). We get easier anonymous inner classes fast, and the correct power of BGGA in Java 8. I can see no real downside, except maybe for some lost pride in some camps. :)

Cheers,
Mikael Grev

Published at DZone with permission of its author, Mikael Grev.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Brian Sayatovic replied on Thu, 2008/08/14 - 12:08pm

I think this is a poor reason to trigger action on the closure front.

<blockquote>...Java will be nuked in the blogosphere ...</blockquote>

 Isn't it bad enough that politics are swayed too strongly by the media?  Do our programming languages need to be as well?

Brian Sayatovic replied on Thu, 2008/08/14 - 12:09pm

Without getting into specifics, I think that implenting the small pieces that could support any of the proposals makes sense.  It will give time to work these into the compilers, IDEs, books, etc. and even get people a chance to experience them to make a more-educated decision about which proposal to support.

 And I'm a guy to still believes we don't neee closures!

Mikael Grev replied on Thu, 2008/08/14 - 12:34pm in response to: Brian Sayatovic

I think this is a poor reason to trigger action on the closure front.

<blockquote>...Java will be nuked in the blogosphere ...</blockquote>

 It is most definitely so. But there is a way that it should be, and there is a way that it is. It is a fine line to walk. That is why I think this middle ground is good. Because it will ease the complains but still not give in to the Java 3000 camp and go full BGGA without testing it first jsut to stay on par with (insert your favorite language here).

Torbjörn Gannholm replied on Thu, 2008/08/14 - 5:03pm

Not convincing, I think it would be better to give it all more thought. Some thoughts:

It's not only about how to create the closure but also how to invoke it, an invocation should have a meaningful name in the context, not something lame like "invoke" or even "actionPerformed".

Also, you have one declaration without a name at all and one with a name "actionPerformed" and a parameter. If any name should be given it should be one that leads to a specification of a contract, i.e. an interface name in java.

For my own part I am finding anonymous classes less and less tasteful, although it would be handy to be able to specify one-liners easily. Moving towards named nested or inner classes you lose the need to access local variables and get better encapsulation.

Stephen Colebourne replied on Thu, 2008/08/14 - 7:25pm

The truth is that the whole "closures" debate is just a small part of the greater debate about whether Java should really change at all now. Have generics made the whole picture just too complex to be able to add any more features? Can langauges ever successfully add new features without the ability to make backwards incompatible changes?

Take the matrix of possible options - no change, CICE (simpler inner classes), FCM (just inner methods), FCM (inner methods and method types), BGGA (the whole shebang). And then the individual features: simpler inner classes vs closures that capture 'this' from the enclosing scope. Using return to return to the invoker, or to the enclosing method. Non-local returns or not. Each one of these is a decision point, and each produces a different answer.

I wish there was a 'right' choice, but there isn't - at some point, someone must take a decision. My view is that trying to put anything into a release pre 2010/2011 is unrealistic, and damaging to Java.

 

Brian Sayatovic replied on Thu, 2008/08/14 - 7:29pm in response to: Torbjörn Gannholm

[quote=tobe]

For my own part I am finding anonymous classes less and less tasteful, although it would be handy to be able to specify one-liners easily. Moving towards named nested or inner classes you lose the need to access local variables and get better encapsulation.

[/quote] I whole-heartedly agree with your post, especially the last part. I often start with an anonymous inner class, but quickly evolve into a named nested/inner class or even a top-level class as I need to add additional information and behavior and -- most importantly -- a semantically meaningful name. Java is a strongly-typed language. The language, compiler, IDEs all recognize this. Its a tool to help you. When I see the closure proposals, they all have singatures, but not of them offer the ability to define a semantically meaningful type to be leveraged by the language, compiler, IDE, and -- most painfully -- the human.

Howard Lovatt replied on Fri, 2008/08/15 - 1:24am

I will come clean and say that I have my own proposal: C3S.

This C3S proposal, like yours and CICE, is built round inner classes and has write access to locals.

Your syntax is good, but I also like my C3S syntax and CICE's, I don't mind FCM's and could live with BGGA's, all in all I am not that sensative to a particular syntax. What I don't want to see however is the introduction of another type of thing that requires boxing. Unfortunately BGGA and FCM give us a closure that requires boxing into an object. Java is primarily an OO language and I think everything should be an object and we should avoid more auto-boxing. So provided the proposal creates an object, then I have no problem with it.

The other issues like non-local return can be added later if we really need them and after the dust has settled on the more important part of a short syntax to creat a one off object. I would probably take considerable convincing that adding structural typing is ever going to be a good idea (part of FCM and BGGA).

Mikael Grev replied on Fri, 2008/08/15 - 4:14am in response to: Stephen Colebourne

What I try to promote here is a catious way. One that doesn't change Java much at all, it just touch up the syntax. Then, when we have that, and the argument that anonymous inner classes are so darn cumbersome to write, can we get a clean view on if we need real powerful closures or not.

This is to fight the "all or nothing" problem.

Howard Lovatt replied on Fri, 2008/08/15 - 4:43am

I agree with you that we should introduce a minimum subset and see if that is all people really want. I suggest the minimum subset should be:

  1. Short syntax for creating an instance of a single-abstract-method type (syntax sugar for an inner class)
  2. Allow read of any local variable (in inner classes as well)
  3. Allow a local variable to be annotaded in some way (e.g. public, volatile, or @Shared) to allow write to local (in inner classes as well)

Mikael Grev replied on Fri, 2008/08/15 - 4:47am in response to: Howard Lovatt

Thank you Howard. Your opinion means a lot since you are the author of the always forgotten C3S closure proposal. I guess people can only have "three" proposals in memory. ;)

Scott Palmer replied on Fri, 2008/08/15 - 8:46am

All of these closure proposals seem to be change for the sake of change.  Everytime I read one of them and look at the examples where the inventor says "see how much better it is with my XYZ idea?" I have to answer, "No, I don't see the advantage."

You've saved a couple keystrokes at the cost of not clarifying intent, but adding confusion...  I always look at the examples and have to figure out what do they really mean and convert in my head back to the standard Java with inner clases syntax that I already know.  Therefore the code is always HARDER to read.   Shorter code is not easier to read AND UNDERSTAND than more verbose code.  It's simply faster to read - without understanding.

I remain unconvinced that there is ANY value in ANY of the closure proposals... It seems to me that people should be using Scala or some other language if this is what they want.  I still don't see the need in Java that is being addressed by these proposals.  If less typing is the need.. then the cost (harder to understand code) is too high.

Consider generics - it eliminated some casts.. but ultimately added more typing in all the declarations and definitions that used generics.  That extra typing CLARIFIED the intent of the code - it made it easier to read, though more verbose.  These closure proposals do the opposite.

Stephen Colebourne replied on Fri, 2008/08/15 - 10:36am

Scott, as well as the "closure"/"simpler inner class" concept, FCM (and more recently BGGA in its implementation) support method/constructor/field references. These are type-safe ways to get hold of a reference to a method or field and pass it to a method where an interface like ActionListener or Runnable is required. This kind of type-safety - no reflection, no non-refactorable strings - is something only a new language feature can support, and has major benefits for any code that integrates with a framework.

Howard, the structurl typing in FCM (method types) I now consider to be an optional part of the FCM spec. Thus you can consider FCM either with or without structual types.

Jeroen Wenting replied on Fri, 2008/08/15 - 11:46am in response to: Brian Sayatovic

[quote=Trinition]

I think this is a poor reason to trigger action on the closure front.

<blockquote>...Java will be nuked in the blogosphere ...</blockquote>

 Isn't it bad enough that politics are swayed too strongly by the media?  Do our programming languages need to be as well?

[/quote]

 Couldn't have said it better myself. As the ONLY reason anyone has been able to come up with to add closures (aka function pointers) is that it would look "kewl" (and now that it would be bad not to add them after they've been talked about so much, a self-fullfilling prophecy if there ever was one) there's no reason for them at all.

Noone has come up with any reasoning to add them that makes them look like more than an utter abomination to me. I've been using Java professionally for over a decade in everything from web applications to EJB applications to web services to commandline tools to graphical user interfaces and I've NEVER once come across a scenario where they'd be more than a clunky way to save a few keystrokes by adding more obfuscation (and wasn't that the reason why goto was not put into the language?).

Mark Thornton replied on Fri, 2008/08/15 - 12:47pm in response to: Jeroen Wenting

The proposed fork/join framework (166y) would often be used with 'methods' having very small bodies. In these cases, without closures, the actual content would be lost amid all the boiler plate.

Jeroen Wenting replied on Fri, 2008/08/15 - 3:20pm in response to: Mark Thornton

[quote=mt79448]The proposed fork/join framework (166y) would often be used with 'methods' having very small bodies. In these cases, without closures, the actual content would be lost amid all the boiler plate.[/quote]

 which says more about the design of that framework than the supposed "need" for function pointers.

Alexander Grünewald replied on Sat, 2008/08/16 - 1:16am

I played with the BGGA prototype and I was very impressed by it's features.
So we now have an exceptional good closures proposal and we shouldn't cripple it.
I guess the best way to resolve the closures issue is a strong and decisive leadership.

Mark Thornton replied on Sat, 2008/08/16 - 2:18am in response to: Jeroen Wenting

[quote=jwenting]  which says more about the design of that framework than the supposed "need" for function pointers.[/quote]

No it is the nature of many of the tasks which the framework is designed to support.

Alex(JAlexoid) ... replied on Sat, 2008/08/16 - 4:32pm in response to: Jeroen Wenting

[quote=Jeroen Wenting]Noone has come up with any reasoning to add them that makes them look like more than an utter abomination to me. I've been using Java professionally for over a decade in everything from web applications to EJB applications to web services to commandline tools to graphical user interfaces and I've NEVER once come across a scenario where they'd be more than a clunky way to save a few keystrokes by adding more obfuscation (and wasn't that the reason why goto was not put into the language?).[/quote]

 The fact that you haven't come acrtoss a scenario, is because you think inside the Java constraints.
 The scanrios are pretty obvious, it's for fine grained transportable/transferable logic. The kind, where you don't want to create a framework(remember how many frameworks Java has) nor create a distinct class nor to pollute the existing class with a tonn of interfaces.

Jeroen Wenting replied on Sun, 2008/08/17 - 5:19am in response to: Mark Thornton

[quote=mt79448]

[quote=jwenting]  which says more about the design of that framework than the supposed "need" for function pointers.[/quote]

No it is the nature of many of the tasks which the framework is designed to support.

[/quote]

 Which indicates Java isn't the "perfect" solution for everything under the Sun.
That doesn't mean we need to pollute and corrupt Java with "features" to mimmick every other programming language out there, which is what's happening.

It means someone needs to realise that Java isn't and can never be the single language one needs to know to do everything. Choose the tools appropriate to the job, don't try to turn a sledgehammer into a precision screwdriver if you want to fit a tiny screw.

Mark Thornton replied on Sun, 2008/08/17 - 6:02am in response to: Jeroen Wenting

[quote=jwenting] Which indicates Java isn't the "perfect" solution for everything under the Sun.
That doesn't mean we need to pollute and corrupt Java with "features" to mimmick every other programming language out there, which is what's happening.[/quote]

But nor should we close off all future change. The trick is in selecting the right features to add. My personal favourite would be to reify generics and extend them to primitives. This could actually reduce the size of the language in the sense that quite a few of the warts in generics would disappear. More would work as one might expect, and Angelika Langer's FAQ could be pruned.

[quote=jwenting]It means someone needs to realise that Java isn't and can never be the single language one needs to know to do everything. Choose the tools appropriate to the job, don't try to turn a sledgehammer into a precision screwdriver if you want to fit a tiny screw.[/quote]

Nor is it likely that any other language will ever be that single tool.

Sometimes it may be better to use a tool you know very well instead of cutting yourself on a more appropriate tool that is entirely unfamiliar. Using too many languages within a single system brings problems of its own. So even each piece is written in the ideal language, managing and maintaining the system as a whole can then be a nightmare.

For these reasons it is worth considering what features can comfortably be added to Java.

Torbjörn Gannholm replied on Sun, 2008/08/17 - 11:43am in response to: Alex(JAlexoid) Panzin

[quote=jalexoid]

 The fact that you haven't come acrtoss a scenario, is because you think inside the Java constraints.

[/quote]

 

The art of programming is exactly to express an algorithm within the constraints of the chosen programming language, in the way that is most clear and idiomatic in that language.

Alex(JAlexoid) ... replied on Sun, 2008/08/17 - 11:51am in response to: Torbjörn Gannholm

[quote=Torbjörn Gannholm]The art of programming is exactly to express an algorithm within the constraints of the chosen programming language, in the way that is most clear and idiomatic in that language.[/quote]

Can't argue with that statement. But where does innovation and/or evolution fit into that?

Howard Lovatt replied on Sun, 2008/08/17 - 8:40pm in response to: Alexander Grünewald

@Alexander,

There are many downsides to the semantics of closures in BGGA, for instance no fields, no inheritance, no recursion and to get them to interoperate with normal objects they require boxing. I think a solution that fits in better with Java is to use a short syntax for an inner class. Apart from simplyfyinging the langauge extension, no new concepts, using inner class semantics allows easy refactoring between the new short syntax, anonymous inner classes, and named inner classes.

Pete Cox replied on Sun, 2008/08/17 - 11:57pm in response to: Scott Palmer

I always look at the examples and have to figure out what do they really mean and convert in my head back to the standard Java with inner clases syntax that I already know.

 

And for me, that's a key stumbling block; in essence falling back to much maligned inner classes.

Anonymous inner classes are often difficult to test, non-reusable (leading to copious copy and paste in the hands of the lazy) and for the event listener example mentioned, difficult to detach. They have their place but aren't always terribly maintainable. So such potential for misuse tempers my enthusiasm for closures.

J Szy replied on Mon, 2008/08/18 - 4:18am in response to: Alex(JAlexoid) Panzin

[quote=jalexoid]

The kind, where you don't want to create a framework(remember how many frameworks Java has) nor create a distinct class nor to pollute the existing class with a tonn of interfaces.

[/quote]

It sounds like throwing a thunk of code in a quick and dirty way at another class or thread. I'm glad Java makes it difficult and hope it will continue to do so.

Mark Thornton replied on Mon, 2008/08/18 - 4:37am in response to: J Szy

[quote=partyzant]

It sounds like throwing a thunk of code in a quick and dirty way at another class or thread. I'm glad Java makes it difficult and hope it will continue to do so.

[/quote]

Do you have any idea of experience of the kind of code you are dismissing out of hand? In particular do you know anything about the fork/join frame work and the fine grained parallelisation enabled by the Parallel*Array classes?

Brian Sayatovic replied on Mon, 2008/08/18 - 7:46am in response to: Alex(JAlexoid) Panzin

[quote=jalexoid] ...it's for fine grained transportable/transferable logic... [/quote]

So you can have a snippet of logic that is dettached from any type definition and anonymously pass it around?  At least an anonymous inner class must implement some well-defined interface or base class.

When all you have is the inputs and outputs, but no semantic definition of what the logic does, you're throwing part o fthe power of Java out.  If you want to anomymous snippets of logic, why not use a functional language?

Java is a strongly-typed, class-based object-oriented programming language.  I don't see a closure as being any of those.

Armin Ehrenreich replied on Mon, 2008/08/18 - 9:30am in response to: Alex(JAlexoid) Panzin

 

But where does innovation and/or evolution fit into that?

But closures are neither new nor innovative. They where around for decades, just look at Smalltalk and many functional languages.

They are simply the feature of the season as was aspect oriented programming last season. As Ruby is build around closures and Ruby was a hip language because of the Rails framework, people suddenly wanted to mimic the programing style of Ruby with Java. (They could simply use Groovy, but this simple solution is seldom mentioned) But no innovation or evolution anywhere. Imagine what would happen if Java continues to include every feature of the season!

I am personally for simplifying the syntax of inner classes as has been proposed in the CICE proposal by Josh Bloch and Doug Lea. Most of the advantages of closures can be achieved this way, especially the fork/join framework

If Sun wants to to have evolution then I would suggest to fix as many bugs as possible and rework generics. Something that really works and is simple, is always hip !

Lets declare these to be the features of the next season that Java has urgently to adapt to otherwise it is doomed :-)

 

Mark Thornton replied on Mon, 2008/08/18 - 9:45am in response to: Armin Ehrenreich

[quote=aehrenr]

 They could simply use Groovy, but this simple solution is seldom mentioned[/quote]

Obviously that solution isn't applicable to the fork/join use case. My understanding is that it was fork/join that initially prompted the closure proposals. The other use cases came later.

Armin Ehrenreich replied on Mon, 2008/08/18 - 11:06am in response to: Mark Thornton

For these reasons it is worth considering what features can comfortably be added to Java.

But with BGGA closures the basic "style" of the APIs and language would change. Just look at Ruby, how the language is used and how the APIs are used. This isn't similar to Java. Not to mention the unfortunate possibility to define new control structures. This is not even similar to the "feeling" of Java. Not that I think that Scala is a bad idea, but Java must not try to copy Scala and Scala is much to complicated to ever become a mainstream language.

Comment viewing options

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