NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed. (sponsored)
In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.
Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.
Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
If you say that you don't like closures you immediately get this in return:
"That is because you don't understand how good they are. Look at language xxxx to see how useful they are and how many keystrokes you save and what cool things you can do that you can't do with Java"
. This has been a major pain when arguing against closures i Java since I always end up on the defensive side explaining that it would be good for some, but not for most, and the people it wouldn't be good for is not actually me. Confusing? Yes. Read on.
What Problems do Closures Solve?
When changing something there's a cost. For instance everyone have to relearn it and that costs resources. The benefits must be proven to be measurably greater than the costs or we are doing it just because it's cool or plays well with our ego.
The benefits with closures are commonly answered with a code snippet of some cool thing you can do that is using less than half of the keystrokes that an anonymous inner class would typically take. This isn't interesting at all to me as I typically just use a couple of keystrokes to create the anonymous inner class. IDEA is filling in the blanks for me and Ctrl+Shift+Space counts as one keystroke in my book. I would guess that the more advanced coders, the ones that is usually on the closure side, does this as well, so the inverted keystroke battle is irrelevant IMO.
Then we have the aesthetics. Anonymous Inner Classes (AIC henceforth) aren't pretty, they actually looks like shit. Closures on the other hand, in their purest form at least, looks very good, almost sexy (to a developer . That is unless you have to use one of the proposed syntaxes for handling exceptions thrown in the closure or have some funky return structure. The solution to this aesthetics problem isn't closures though, it can be solved without adding complexity by just allowing a little syntactic sugar for the AICs. They can be done so much prettier (and with less keystrokes for those non-IDEA users) in simple ways and there are examples of this floating around the net.
Then there is the "Closures can do many things that AICs can't. Change the variables outside their scope for instance". I'm not sure this is such a great idea. I think it somewhat breaks the KISS principle and the "what you see is what you get" idea that Java is based upon. Bug fixing and support is in larger projects a greater cost than saved keystrokes and this would lead to new types of hard to understand bugs. I know you can do really fancy stuff but on the other hand I haven't really felt the need for this yet and I have been writing code for a long time. Sure, it's another tool in the toolbox, but a tool that is looking for a usage rather than the other way around. If needed we could drop the requirement for the "final" variable declaration but I still think that the AIC should only be working on a copy of the value. The final is not the ultimate bug defending solution anyway since it just enforces the reference or primitive value and not the properties of that object.
Closures solve some problems and use-cases, but most of them have much simpler solutions that doesn't complicate things.
What is the Cost of Adding Closures?
There is a cost to everything. The primary cost here is that Java developers need to learn new constructs. Constructs that are not very Java-ish and therefore will take some time to getting used to. The concept of closures is more involved than AIC, and I know some are struggling with AICs... Remember that not all are as bright as you and you gain nothing from alienating the Java-Joes however good that feels for your ego. In fact there is a good chance you'll have quite a few Java-Joes in your team, since average is average and half of the developers is below average (I know, the
median
really).
Sun has made it clear that they need to make Java easier for the newbies to reach its goal of ten million Java developers. In fact simplicity has been a major theme for quite some time now. Java stands for KISS regarding the language and it is really the APIs such as JEE and Swing that are targeted by Sun in this matter. Closures goes the other way. It makes the Java language harder to grasp. So Sun is making the APIs easier to use but are suggesting that the language itself should trade simplicity for power. Not very consistent.
Carrying the Legacy
You favorite "other" language probably has closures. I have nothing against that. Those languages were created with closures in mind and when you learned them closures was in the APIs. With Java the problem is that the APIs weren't created with closures in mind and they aren't supported without jumping through hoops. Take the much loved Collection framework. If it'd been closure-enabled from day one it would've been even better. Now you need to squeeze in closures either by creating a new, alternate, Collections framework with closure syntax support or by using other more "fancy" wrapping constructs. Bottom line: Buying G-Strings for your middle age wife doesn't make her look 18 again. Sorry.
Conclusion
I think that closures are the rocket scientist's answer to a problem that can be solved by a plumber and a carpenter. If closures would have been here from the beginning I would have loved it but that is not the case and there's nothing we can do about that now. C++ went down the power over simplicity road and never came back. Closures is the
Pimp My Ride
answer to more efficient car pooling.
Disclaimer
If closures gets added I will use them and like them. I will make cool constructs that saves keystrokes and I won't abuse them, which is possible (but that goes for just about anything). I'm probably not the average user though and when writing this I'm thinking about the prosperity of the Java platform not my personal satisfaction.
Mikael, were you at Javapolis? Neal Gafter did a great presentation there about closures, as well as a BOF. He has
written
a little about his experience there. Some key points from the talk to guide the rest of this discussion:
Firstly, the key use case Neal envisages is control flow abstraction. That is, allowing you as a developer to effectively add new keywords to the language. Logically, existing keywords such as synchronized and foreach could be represented in this way (although they wouldn't of course be changed). Neal presented some very clear examples as to why giving developers keyword control is A Good Thing.
The opposing point of view is that ordinary developers should be prevented from adding such API based keywords. This is the part of the intention behind the
alternative proposal
(CICE). Neal was crystal clear that CICE does not meet the use case he is focussed on - that of giving control abstraction power to ordinary developers without excessive complexity.
Secondly, the closure proposal has basically nothing at all to do with inner classes. The implementation may use inner classes, or it may not - thats a compiler detail. As such, developers learning Java will probably be asked to think of closures as 'flexible keywords' rather than an 'alternative syntax for inner classes'.
A related issue is what break, continue, this and return do within a closure. On this point, the proposal is clear - they must behave exactly the same as they would if the code was not surrounded by the closure*. This behaviour is of course entirely different (and simpler!) than that of inner classes. (*Note that there is one situation where this isn't true, and personally I have concerns about that situation)
Here are two examples (that I am remembering from the talk as best I can):
importstatic java.util.Collections.eachEntry;
Map<String, Integer> map = ...
eachEntry(String key, Integer value : map) {
// do stuff with key and value
}
In this example, you can see how you would import the closure implementation using the existing static import. (A closure implementation is basically just a method). The map is passed into the closure method, which calls the block of code for each entry in the map setting up the correct key and value elements.
The key point is that this looks very much like a new language keyword, or a small change to the Java 5 enhanced for loop, but it isn't. Its an API method on the Collections class.
A second example, from Google code:
importstatic com.google.GoogleUtils.performanceTime;
performanceTime("gmailPerformanceLog.txt") {
// code to be timed and logged for performance monitoring
}
The point with this example was that this particular closure is an API method. There is no way anyone would want to add a new keyword to the Java language to monitor performance in a Google application!
Finally, the proposal presented at Javapolis is v0.4 of the spec. It has evolved a lot since v0.1, and will almost certainly be tweaked further.
I have no chance to battle Neal when it comes to technical details here. I've focused what I think is what's most important which is
why
and not the
how
that is what everyone is arguing about.
As for your last example it is actually pretty good one. I would use another construct for it though, one that I think is added to Dolphin and I like (from C#).
using(new PerformanceTimer("gmailPerformanceLog.txt")) {
// code to be timed and logged for performance monitoring
}
The using keyword (or similar) would be very easy to understand and as long as you make PerformanceTimer "Closable" (or similar) it will be automatically cleaned up when the block ends.
User specifiable keywords makes me very afraid. #DEFINE in C++ has many things going for it as well, that doesn't mean it was a good construct.
Having attended Javapolis, I have moved distinctly towards supporting closures. A key point for Javalobby contributors however (who are often client/swing focussed). The closure proposal is not driven by the use case of making adding an action listener easier. It is driven by the control abstraction use case. These are (IMO) two very different use cases, and greatly impact how you view the technology called 'closures'.
I now believe that the BGGA closure proposal would change the language significantly for the better. It doesn't greatly add complexity, and its certainly something that my own junior developers could pick up in a few minutes.
A second benefit is that it reduces the need for future language changes. There are literally hundreds of ideas for changes in the Java language. Much of that pressure will go away if senior developers have the power to add the expressiveness they need themselves. (To be clear - only senior developers should ever try and write a method that defines a closure)
Mikael, your post is very focussed on inner classes as the existing concept. The key point I want to reply with is that inner classes are irrelevant to the closure proposal (BGGA). the confusion arises because of the initial assumption that inner classes will be refactored to become closures. That isn't the primary goal of the proposal.
To address your points:
- "everyone have to relearn it"
True, but I look at it now and see something that people will find incredibly simple to grasp.
- "inverted keystroke battle is irrelevant"
I agree. Closures is not about reducing keystrokes. Its about DRY, code reuse and code clarity.
- "Change the variables outside their scope for instance"
Forget the inner classes view of the world. Closures have nothing to do with inner classes, and everything to do with being a block of code like a synchronized block.
- "you need to squeeze in closures either by creating a new, alternate, Collections framework with closure syntax support or by using other more "fancy" wrapping constructs"
I hope the examples above indicates just how integrated the proposal is now with existing Java syntax, and how there really is no need to change or replace the collections framework.
- "I think that closures are the rocket scientist's answer to a problem that can be solved by a plumber and a carpenter"
I think I'd characterise them as 'one ring to rule them all'. Once we get closures, many, many of the things that we curse today will be solvable, and much of the code that we cut and paste will become refactorable into common methods.
In summary, closures are a different mindset from inner classes, and will be used for a different purpose. The latest syntax looks pretty good, and at the moment it looks like it can be implemented without issue. Except for one, for which I'll start another thread.
I have one serious reservation with the proposal at present. The issue occurs because the closure proposal (BGGA) allows you to use closure syntax to create a swing listener or a Runnable or alike. In these cases, an object is being created which will be executed later, probably on a different thread.
In this environment, the original method where the object was created no longer exists when the object is run. As such break, continue and return have no meaning in relation to the original method. Instead, they will throw a runtime error. This is pretty horrible.
In addition, you cannot tell just by looking at the calling code as to whether you are allowed to write a break/continue/return. You need to look at the API method implementation. This creates a very hard rule for the junior developer to learn - 'you can use break/continue/return in closures and they have their normal meaning, except when you can't...' - yuk.
My preferred solution to this is simple. Do not allow the closure syntax (BGGA) for these situations - event listeners, executables, runnables (referred to a a 'RestrictedClosure' in the latest spec). Instead, these situations should use an anonymous inner class exactly as now.
In other words, I believe there are two clear and distinct use cases for closures, and trying to use the same syntax for both is going to case hell.
I guess there were similar positive things said about every single addition to C++. "With this feature you can do this and that and it is
so
powerful". Frankly (sort of) defining new keywords on a developer level scares the bejesus out of me.
You know how we developers are. We will make increasingly smarter and smarter solutions to problems, and with a feature like closures you have the power to
fix Java
on a developer by developer basis. Can anything good come out of that? It is very non-Java.
I don't know why but I haven't felt the need to "have more power" with Java. Instead I like it that you can with clean simple Java create applications and APIs that everybody understands and WYSIWYG.
The only thing I see as really good with closures, given that there won't be a simplification of Anonymous Inner Classes is that you can make listener code much simpler.
Why is everybody always talking about closures yes or no?
It could be a nice addition if done right and simple. I do like method pointers that for example javascript does have that you can give a method another method pointer as argument and then call invoke in it. Instead of the anonymous inner class. That would be nice.
But what i also would like to see are "mixed types" or "type enhancers". Because i do so many times copy past of code that is just horrible (implementations of interfaces which impl is pretty much the same for all impls but they can't have a commons base class)
> I do like method pointers that for example javascript does have that you can give a method another method pointer as argument and then call invoke in it. Instead of the anonymous inner class. That would be nice.
I concur, I would like this as well. If done right.
I was referring to closures in the forms that they are currently suggested. Closures have a larger set of functionality than function references.
Hi Stephen,
thanks for the examples you quoted they are very interesting, they do however leave me with more questions than answers:
1. How is eachEntry's prototype defined in Collections?
2. Would we need to refactor large portions of the Java API to enable such functionality in a uniform way?
3. Who invokes the closure?
4. Where would the exceptions go? How would checked exceptions behave?
5. How would this be implemented in the VM?
E.g. If "this" would return the standard surrounding class but the implementation would use an inner class, would all calls to this be translated to SurroundingClass.this by the compiler? Won't this open the door for multiple unforeseeable problems?
6. You say that this feature is intended for senior developers but I don't see why? Are there complexities that were mentioned that junior developers should not be aware of?
Generally I tend to be wary from features that are designed for "experts", I find that many of the worse programmers I employed thought they were the best...
Shai Almog
vPrise Software makers of vPrise Workgroup
http://wg.vprise.com/ founder of bean-properties the leading OSS properties implementation in Java https://bean-properties.dev.java.net/
> Frankly (sort of) defining new keywords on a developer level scares the bejesus out of me.
On one side I agree with you, on the other hand it is already possible today.
importstatic java.util.Collections.eachEntry;
Map<String, Integer> map = ...
eachEntry(String key, Integer value : map) {
// do stuff with key and value
}
versus
importstatic my.funny.Utils.eachEntry;
Map<String, Integer> map = ...
eachEntry(map, new MapVisitor<String,Integer>() {
publicvoid visit(String key, Integer value) {
// do stuff with key and value
}
});
Only real difference is that in second case you cannot modify local variables of surrounding method, so for example instead of doing sum+=value, you would have to create int[] sum = new int[1] outside and do sum[0] += value...
Do you really think that second case (current java) is easier to understand for median-Joe? Let's not confuse number of features with ability to understand them (minimalistic languages are often hardest to understand). Java of course is very far from minimal language, but I don't think that new language features should be rejected just on the ground of being a new syntax - you need to see if that syntax allows to express current hackish solutions in more elegant/powerful way.
As I said, Anonymous Inner Classes could get a simpler syntax if they only have one method. There are suggestions about this floating around. This would be good for listener code as well.
If I really need a sum then I would create a new static inner class (or a normal public class if it could be reused) with a sum field and a getSum() method. Yes, a few keystrokes more but IMO it's a lot cleaner.
So for a non-sum version (something like):
Map<String, Integer> map = ...
eachEntry(map, new MapVisitor<String, Integer>(String key, Integer value) {
// do stuff with key and value
});
and for the sum version:
Map<String, Integer> map = ...
MyMapVisitor<String,Integer> visitor = new MyMapVisitor<String,Integer>();
eachEntry(map, visitor);
int sum = visitor.getSum();
// Implementation of the MapVisitor is left as an exercise to the reader ;)
Great approach... now, why can you put code within a class and why can't I just write a class like this one:
class HelloWorld {
System.out.println("Hello World!");
}
? Isn't it clear that I want that code to be performed within the main-method/constructor?
How are you going to explain _that_ to an average developer who can't grasp the meaning of closures?
All of your examples can be written much more Java-like by utilizing closures.
each(String key, Integer value : map) {
// do stuff
}
It looks like the enhanced for-loop and should be pretty clear to the user, because he already knows constructs like that one. Note also that the construct itself won't have to be changed because you can easily access outside variables, just like you could in any other construct.
This is far easier to understand for someone who's new to Java or programming. And it offers more power than a AIC could ever give you.
Good looking Swing: http://pgslookandfeel.dev.java.net
eachEntry(map) {String key, Integer value => ... }
The syntax shown by Stephen is just the shorthand-version - as far as I understand the spec (v 0.3).
I believe his point about "leaving this for senior developers" relates only to the creation of closures, which is a hairy part for sure. Closures are abstractions and sometimes it is quite hard to find a good abstraction and the most obvious way might be wrong, therefore tasks like this might be done better by experienced developers.
The usage, however, is easy for everyone.
Good looking Swing: http://pgslookandfeel.dev.java.net
> All of your examples can be written much more Java-like by utilizing closures.
Hmm. I was using pure Java (with a slight syntactic sugar added for the first example) and you are using closure syntax that is not a Java construct and you say that that construct is actually more Java like? I'm confused.
> now, why can you put code within a class and why can't I just write a class like this one:
Why Closures in Dolphin is a Bad Idea
At 7:31 AM on Dec 16, 2006, Mikael Grev
wrote:
Fresh Jobs for Developers Post a job opportunity
If you say that you don't like closures you immediately get this in return: "That is because you don't understand how good they are. Look at language xxxx to see how useful they are and how many keystrokes you save and what cool things you can do that you can't do with Java" . This has been a major pain when arguing against closures i Java since I always end up on the defensive side explaining that it would be good for some, but not for most, and the people it wouldn't be good for is not actually me. Confusing? Yes. Read on.
What Problems do Closures Solve?
When changing something there's a cost. For instance everyone have to relearn it and that costs resources. The benefits must be proven to be measurably greater than the costs or we are doing it just because it's cool or plays well with our ego.The benefits with closures are commonly answered with a code snippet of some cool thing you can do that is using less than half of the keystrokes that an anonymous inner class would typically take. This isn't interesting at all to me as I typically just use a couple of keystrokes to create the anonymous inner class. IDEA is filling in the blanks for me and Ctrl+Shift+Space counts as one keystroke in my book. I would guess that the more advanced coders, the ones that is usually on the closure side, does this as well, so the inverted keystroke battle is irrelevant IMO.
Then we have the aesthetics. Anonymous Inner Classes (AIC henceforth) aren't pretty, they actually looks like shit. Closures on the other hand, in their purest form at least, looks very good, almost sexy (to a developer
. That is unless you have to use one of the proposed syntaxes for handling exceptions thrown in the closure or have some funky return structure. The solution to this aesthetics problem isn't closures though, it can be solved without adding complexity by just allowing a little syntactic sugar for the AICs. They can be done so much prettier (and with less keystrokes for those non-IDEA users) in simple ways and there are examples of this floating around the net.
Then there is the "Closures can do many things that AICs can't. Change the variables outside their scope for instance". I'm not sure this is such a great idea. I think it somewhat breaks the KISS principle and the "what you see is what you get" idea that Java is based upon. Bug fixing and support is in larger projects a greater cost than saved keystrokes and this would lead to new types of hard to understand bugs. I know you can do really fancy stuff but on the other hand I haven't really felt the need for this yet and I have been writing code for a long time. Sure, it's another tool in the toolbox, but a tool that is looking for a usage rather than the other way around. If needed we could drop the requirement for the "final" variable declaration but I still think that the AIC should only be working on a copy of the value. The final is not the ultimate bug defending solution anyway since it just enforces the reference or primitive value and not the properties of that object.
Closures solve some problems and use-cases, but most of them have much simpler solutions that doesn't complicate things.
What is the Cost of Adding Closures?
There is a cost to everything. The primary cost here is that Java developers need to learn new constructs. Constructs that are not very Java-ish and therefore will take some time to getting used to. The concept of closures is more involved than AIC, and I know some are struggling with AICs... Remember that not all are as bright as you and you gain nothing from alienating the Java-Joes however good that feels for your ego. In fact there is a good chance you'll have quite a few Java-Joes in your team, since average is average and half of the developers is below average (I know, the median really).Sun has made it clear that they need to make Java easier for the newbies to reach its goal of ten million Java developers. In fact simplicity has been a major theme for quite some time now. Java stands for KISS regarding the language and it is really the APIs such as JEE and Swing that are targeted by Sun in this matter. Closures goes the other way. It makes the Java language harder to grasp. So Sun is making the APIs easier to use but are suggesting that the language itself should trade simplicity for power. Not very consistent.
Carrying the Legacy
You favorite "other" language probably has closures. I have nothing against that. Those languages were created with closures in mind and when you learned them closures was in the APIs. With Java the problem is that the APIs weren't created with closures in mind and they aren't supported without jumping through hoops. Take the much loved Collection framework. If it'd been closure-enabled from day one it would've been even better. Now you need to squeeze in closures either by creating a new, alternate, Collections framework with closure syntax support or by using other more "fancy" wrapping constructs. Bottom line: Buying G-Strings for your middle age wife doesn't make her look 18 again. Sorry.Conclusion
I think that closures are the rocket scientist's answer to a problem that can be solved by a plumber and a carpenter. If closures would have been here from the beginning I would have loved it but that is not the case and there's nothing we can do about that now. C++ went down the power over simplicity road and never came back. Closures is the Pimp My Ride answer to more efficient car pooling.Disclaimer
If closures gets added I will use them and like them. I will make cool constructs that saves keystrokes and I won't abuse them, which is possible (but that goes for just about anything). I'm probably not the average user though and when writing this I'm thinking about the prosperity of the Java platform not my personal satisfaction.Cheers,
Mikael Grev
119 replies so far (
Post your own)
Summary from Javapolis
Mikael, were you at Javapolis? Neal Gafter did a great presentation there about closures, as well as a BOF. He has written a little about his experience there. Some key points from the talk to guide the rest of this discussion:Firstly, the key use case Neal envisages is control flow abstraction. That is, allowing you as a developer to effectively add new keywords to the language. Logically, existing keywords such as synchronized and foreach could be represented in this way (although they wouldn't of course be changed). Neal presented some very clear examples as to why giving developers keyword control is A Good Thing.
The opposing point of view is that ordinary developers should be prevented from adding such API based keywords. This is the part of the intention behind the alternative proposal (CICE). Neal was crystal clear that CICE does not meet the use case he is focussed on - that of giving control abstraction power to ordinary developers without excessive complexity.
Secondly, the closure proposal has basically nothing at all to do with inner classes. The implementation may use inner classes, or it may not - thats a compiler detail. As such, developers learning Java will probably be asked to think of closures as 'flexible keywords' rather than an 'alternative syntax for inner classes'.
A related issue is what break, continue, this and return do within a closure. On this point, the proposal is clear - they must behave exactly the same as they would if the code was not surrounded by the closure*. This behaviour is of course entirely different (and simpler!) than that of inner classes. (*Note that there is one situation where this isn't true, and personally I have concerns about that situation)
Here are two examples (that I am remembering from the talk as best I can):
import static java.util.Collections.eachEntry; Map<String, Integer> map = ... eachEntry(String key, Integer value : map) { // do stuff with key and value }In this example, you can see how you would import the closure implementation using the existing static import. (A closure implementation is basically just a method). The map is passed into the closure method, which calls the block of code for each entry in the map setting up the correct key and value elements.
The key point is that this looks very much like a new language keyword, or a small change to the Java 5 enhanced for loop, but it isn't. Its an API method on the Collections class.
A second example, from Google code:
import static com.google.GoogleUtils.performanceTime; performanceTime("gmailPerformanceLog.txt") { // code to be timed and logged for performance monitoring }The point with this example was that this particular closure is an API method. There is no way anyone would want to add a new keyword to the Java language to monitor performance in a Google application!
Finally, the proposal presented at Javapolis is v0.4 of the spec. It has evolved a lot since v0.1, and will almost certainly be tweaked further.
Re: Summary from Javapolis
Thanks for the detailed answer!> Mikael, were you at Javapolis?
Nope. I wanted to go but couldn't make the time.
I have no chance to battle Neal when it comes to technical details here. I've focused what I think is what's most important which is why and not the how that is what everyone is arguing about.
As for your last example it is actually pretty good one. I would use another construct for it though, one that I think is added to Dolphin and I like (from C#).
using(new PerformanceTimer("gmailPerformanceLog.txt")) { // code to be timed and logged for performance monitoring }The using keyword (or similar) would be very easy to understand and as long as you make PerformanceTimer "Closable" (or similar) it will be automatically cleaned up when the block ends.
User specifiable keywords makes me very afraid. #DEFINE in C++ has many things going for it as well, that doesn't mean it was a good construct.
Cheers,
MiG Java Calendar Component, MiG Layout for Swing/SWT (Vote -> JDK)
Re: Why Closures in Dolphin is a Bad Idea
And now my reply to the original postHaving attended Javapolis, I have moved distinctly towards supporting closures. A key point for Javalobby contributors however (who are often client/swing focussed). The closure proposal is not driven by the use case of making adding an action listener easier. It is driven by the control abstraction use case. These are (IMO) two very different use cases, and greatly impact how you view the technology called 'closures'.
I now believe that the BGGA closure proposal would change the language significantly for the better. It doesn't greatly add complexity, and its certainly something that my own junior developers could pick up in a few minutes.
A second benefit is that it reduces the need for future language changes. There are literally hundreds of ideas for changes in the Java language. Much of that pressure will go away if senior developers have the power to add the expressiveness they need themselves. (To be clear - only senior developers should ever try and write a method that defines a closure)
Mikael, your post is very focussed on inner classes as the existing concept. The key point I want to reply with is that inner classes are irrelevant to the closure proposal (BGGA). the confusion arises because of the initial assumption that inner classes will be refactored to become closures. That isn't the primary goal of the proposal.
To address your points:
- "everyone have to relearn it"
True, but I look at it now and see something that people will find incredibly simple to grasp.
- "inverted keystroke battle is irrelevant"
I agree. Closures is not about reducing keystrokes. Its about DRY, code reuse and code clarity.
- "Change the variables outside their scope for instance"
Forget the inner classes view of the world. Closures have nothing to do with inner classes, and everything to do with being a block of code like a synchronized block.
- "you need to squeeze in closures either by creating a new, alternate, Collections framework with closure syntax support or by using other more "fancy" wrapping constructs"
I hope the examples above indicates just how integrated the proposal is now with existing Java syntax, and how there really is no need to change or replace the collections framework.
- "I think that closures are the rocket scientist's answer to a problem that can be solved by a plumber and a carpenter"
I think I'd characterise them as 'one ring to rule them all'. Once we get closures, many, many of the things that we curse today will be solvable, and much of the code that we cut and paste will become refactorable into common methods.
In summary, closures are a different mindset from inner classes, and will be used for a different purpose. The latest syntax looks pretty good, and at the moment it looks like it can be implemented without issue. Except for one, for which I'll start another thread.
The asynchronous use case
I have one serious reservation with the proposal at present. The issue occurs because the closure proposal (BGGA) allows you to use closure syntax to create a swing listener or a Runnable or alike. In these cases, an object is being created which will be executed later, probably on a different thread.In this environment, the original method where the object was created no longer exists when the object is run. As such break, continue and return have no meaning in relation to the original method. Instead, they will throw a runtime error. This is pretty horrible.
In addition, you cannot tell just by looking at the calling code as to whether you are allowed to write a break/continue/return. You need to look at the API method implementation. This creates a very hard rule for the junior developer to learn - 'you can use break/continue/return in closures and they have their normal meaning, except when you can't...' - yuk.
My preferred solution to this is simple. Do not allow the closure syntax (BGGA) for these situations - event listeners, executables, runnables (referred to a a 'RestrictedClosure' in the latest spec). Instead, these situations should use an anonymous inner class exactly as now.
In other words, I believe there are two clear and distinct use cases for closures, and trying to use the same syntax for both is going to case hell.
Re: Summary from Javapolis
Thanks for sharing Stephen,I wish I was there ~
Re: Why Closures in Dolphin is a Bad Idea
I guess there were similar positive things said about every single addition to C++. "With this feature you can do this and that and it is so powerful". Frankly (sort of) defining new keywords on a developer level scares the bejesus out of me.You know how we developers are. We will make increasingly smarter and smarter solutions to problems, and with a feature like closures you have the power to fix Java on a developer by developer basis. Can anything good come out of that? It is very non-Java.
I don't know why but I haven't felt the need to "have more power" with Java. Instead I like it that you can with clean simple Java create applications and APIs that everybody understands and WYSIWYG.
The only thing I see as really good with closures, given that there won't be a simplification of Anonymous Inner Classes is that you can make listener code much simpler.
But I might just be getting old..
Cheers,
MiG Java Calendar Component, MiG Layout for Swing/SWT (Vote -> JDK)
Re: Why Closures in Dolphin is a Bad Idea
Why is everybody always talking about closures yes or no?It could be a nice addition if done right and simple. I do like method pointers that for example javascript does have that you can give a method another method pointer as argument and then call invoke in it. Instead of the anonymous inner class. That would be nice.
But what i also would like to see are "mixed types" or "type enhancers". Because i do so many times copy past of code that is just horrible (implementations of interfaces which impl is pretty much the same for all impls but they can't have a commons base class)
Jonathan Locke has 3 blogs about them:
http://jroller.com/page/JonathanLocke/20060329
and a proposal pdf: http://www.muppetlabs.com/~jonl/TypeEnhancers.pdf
Re: Why Closures in Dolphin is a Bad Idea
> I do like method pointers that for example javascript does have that you can give a method another method pointer as argument and then call invoke in it. Instead of the anonymous inner class. That would be nice.I concur, I would like this as well. If done right.
I was referring to closures in the forms that they are currently suggested. Closures have a larger set of functionality than function references.
Cheers,
MiG Java Calendar Component, MiG Layout for Swing/SWT (Vote -> JDK)
Re: Summary from Javapolis
Hi Stephen,thanks for the examples you quoted they are very interesting, they do however leave me with more questions than answers:
1. How is eachEntry's prototype defined in Collections?
2. Would we need to refactor large portions of the Java API to enable such functionality in a uniform way?
3. Who invokes the closure?
4. Where would the exceptions go? How would checked exceptions behave?
5. How would this be implemented in the VM?
E.g. If "this" would return the standard surrounding class but the implementation would use an inner class, would all calls to this be translated to SurroundingClass.this by the compiler? Won't this open the door for multiple unforeseeable problems?
6. You say that this feature is intended for senior developers but I don't see why? Are there complexities that were mentioned that junior developers should not be aware of?
Generally I tend to be wary from features that are designed for "experts", I find that many of the worse programmers I employed thought they were the best...
Re: Why Closures in Dolphin is a Bad Idea
> Frankly (sort of) defining new keywords on a developer level scares the bejesus out of me.On one side I agree with you, on the other hand it is already possible today.
import static java.util.Collections.eachEntry; Map<String, Integer> map = ... eachEntry(String key, Integer value : map) { // do stuff with key and value }versus
import static my.funny.Utils.eachEntry; Map<String, Integer> map = ... eachEntry(map, new MapVisitor<String,Integer>() { public void visit(String key, Integer value) { // do stuff with key and value } });Only real difference is that in second case you cannot modify local variables of surrounding method, so for example instead of doing sum+=value, you would have to create int[] sum = new int[1] outside and do sum[0] += value...
Do you really think that second case (current java) is easier to understand for median-Joe? Let's not confuse number of features with ability to understand them (minimalistic languages are often hardest to understand). Java of course is very far from minimal language, but I don't think that new language features should be rejected just on the ground of being a new syntax - you need to see if that syntax allows to express current hackish solutions in more elegant/powerful way.
Re: Why Closures in Dolphin is a Bad Idea
As I said, Anonymous Inner Classes could get a simpler syntax if they only have one method. There are suggestions about this floating around. This would be good for listener code as well.If I really need a sum then I would create a new static inner class (or a normal public class if it could be reused) with a sum field and a getSum() method. Yes, a few keystrokes more but IMO it's a lot cleaner.
So for a non-sum version (something like):
Map<String, Integer> map = ... eachEntry(map, new MapVisitor<String, Integer>(String key, Integer value) { // do stuff with key and value });and for the sum version:
Cheers,
MiG Java Calendar Component, MiG Layout for Swing/SWT (Vote -> JDK)
Re: Why Closures in Dolphin is a Bad Idea
Great approach... now, why can you put code within a class and why can't I just write a class like this one:class HelloWorld { System.out.println("Hello World!"); }? Isn't it clear that I want that code to be performed within the main-method/constructor?
How are you going to explain _that_ to an average developer who can't grasp the meaning of closures?
All of your examples can be written much more Java-like by utilizing closures.
each(String key, Integer value : map) { // do stuff }It looks like the enhanced for-loop and should be pretty clear to the user, because he already knows constructs like that one. Note also that the construct itself won't have to be changed because you can easily access outside variables, just like you could in any other construct.
This is far easier to understand for someone who's new to Java or programming. And it offers more power than a AIC could ever give you.
Re: Summary from Javapolis
public static <K,E> void eachEntry({K,E=>void} block, Map<K,E> map) { ... }Or something like that.
The invocation could also be written like this:
eachEntry(map) {String key, Integer value => ... }The syntax shown by Stephen is just the shorthand-version - as far as I understand the spec (v 0.3).
I believe his point about "leaving this for senior developers" relates only to the creation of closures, which is a hairy part for sure. Closures are abstractions and sometimes it is quite hard to find a good abstraction and the most obvious way might be wrong, therefore tasks like this might be done better by experienced developers.
The usage, however, is easy for everyone.
Re: Why Closures in Dolphin is a Bad Idea
> All of your examples can be written much more Java-like by utilizing closures.Hmm. I was using pure Java (with a slight syntactic sugar added for the first example) and you are using closure syntax that is not a Java construct and you say that that construct is actually more Java like? I'm confused.
> now, why can you put code within a class and why can't I just write a class like this one:
That wasn't what I was suggesting.
Cheers,
MiG Java Calendar Component, MiG Layout for Swing/SWT (Vote -> JDK)