Closures in Java and Scala
Ads by DZone
People argue that verbose code is easier to understand. Do you agree when reading these two examples, one method in Java, one in Scala?
public List<Item> bought(User user) {
List<Item> result = new ArrayList();
for (Item item : currentItems) {
if (user.bought(item)) {
result.add(item);
}
}
return result;
}
def bought(user: User) =);
}
}
And without the curly braces:
public List<Item> bought(User user) {The interesting differences between Java with closures and Scala is the static typing: Scala inferences that items are all of type Item, so there is no need to specify that information again. Especially the last example shows that quite clearly.
return items.filter(Item item :) user.bought(item);
}.
0
- Login or register to post comments
- 3195 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)
Uffe Seerup replied on Wed, 2008/05/21 - 1:04pm
I think your example may be a little too simplistic; you would probably not define a method just for this purpose as it would be just as easy and readable to filter on the Items property directly. This is at least true for your Scala example.
In my opinion the current BGGA proposal is skewed by the desire to allow for automatic resource management like the C# using statement. While it would be nice to be able to make such language enhancements yourself, I feel that closures are not the way to obtain it. That desire is responsible for the return problem (very well highlighted by your example) which makes code inside the closure block follow strangely different (non-Java-more-Ruby-like) semantics.
It would make more sense to keep closures simple and then perhaps include some kind of programmable syntax macros, which could allow for simplification of much boilerplate code.
BTW, the C# version of the method would be:
IEnumerable<Item> Bought(User user) {
return items.Where(user.bought);
}
again, in this particular simple example you would just do
Items.Where(user.bought);
Osvaldo Doederlein replied on Wed, 2008/05/21 - 1:47pm
Dmitriy Setrakyan replied on Wed, 2008/05/21 - 5:48pm
Funny thing. Remove the curly braces from Java closures example and the code in Scala is no longer "shorter". One could of course argue if curly braces hurt readability or not. But to me, they are much more readable than that underscore before the closing parenthesis in Scala example.
I do agree that Java could significantly improve with type inference though, especially for generics.
Best
Dmitriy Setrakyan
GridGain - Grid Computing Made Simple
Jeroen Wenting replied on Thu, 2008/05/22 - 3:46am
Let me quote Josh Bloch when asked about closures by DZone:
"Sugrue: What is your opinion on the inclusion Closures in Java 7?
Bloch:."
Couldn't agree more.
joern.zaefferer replied on Thu, 2008/05/22 - 3:50am
Thanks everyone for their comments!
Uffe Seerup: Of course the example is contrived, but thats always the case for examples. Just imagine an additional guard clause in front of the filtering and use that in more that one place - that should be enough of a reason to extract a method.
I'm not too familiar with the details of the BGGA proposal, but according to the presentation Neil Gafter gave on it, its not about resource managment ala using, but rather about control abstractions. Control abstractions would allow a library to implement using, instead of having to add that to the language itself.
Thanks for the C# example.
Osvaldo Doederlein: You could just consider closures as a simplification of anonymous classes.
I'm currently writing a Java web application on top of the Wicket framework. A simplification of anonymous classes would simplify my Wicket components a ton. I'd be happy to delete all that boilerplate code and let the compiler do some more work.
Dmitriy Setrakyan: Good point - I've updated the example accordingly. Now its even more clear that Java + Closures + Type Inference would get as quite close to Scala syntax in that case.
joern.zaefferer replied on Thu, 2008/05/22 - 3:56am
Jeroen Wenting: A major showstopper for using Scala today is the state of tool support. Hyperlinking of code elements, code completion, integration of API documentation, automated refactorings - all that stuff make me much more productive as a programmer. If closures were added to Java, I could leverage that without losing any of the benefits tools provide. Most likely Eclipse would have some additional helper for closures in its next version, too.
The current beta Scala plugin has hyperlinking and completion working, but is otherwise very unstable. I'm looking forward to the point where is actually usable.
Uffe Seerup replied on Thu, 2008/05/22 - 10:03am
joern: The point I was trying to get across (poorly) is that your example is perfectly reasonable in case of Java, but in the case of Scala and indeed any other mainstream language (Ruby, Python, Groovy, C# and even Visual Basic.NET) you would never write the corresponding method in the first place.
In Java you would indeed often choose to code a method for "items bought by user", as coding a loop inline takes away from readability. Loops are not as much read as they must be understood. Thus loops interrupt the reading of code and blurs the main purpose. That is why we like to abstract away loops like yours above.
But for languages that feature list comprehensions you would typically not write such abstractions in the first place, as they introduce an unnessecary level of complexity (you must now read the method to make sure it does what you believe). You would simply use the items list/collection inline with its list comprehension methods. There's no loop to understand.
Therefore closure support hold the potential to drastically cut down on goo code. I believe your example is perfectly viable, but in my opinion you should contrast the Java example with writing no method at all in Scala - and still retain on-par (or better) readability and more flexibility (more predicates than bought can be used).
To complete the example you could show the code where the methods are being used. That would make it more clear that using a closure indeed can increase readability.
Jeroen Wenting replied on Fri, 2008/05/23 - 12:54am
I was talking about the idiocy of introducing closures in Java, not about Scala (of which I have little knowledge, and which was I think designed with them in mind).
Closures (a.k.a. OO function pointers) are something that should be designed into a language from the ground up if you really want it, not retrofitted at some later point (say after 12 years...) to stroke the vanity of some people who like to see their name on a JSR.
Jess Holle replied on Fri, 2008/05/23 - 6:30am
I have to say I much prefer the Java example here, despite liking closures overall -- you can tell what's going on.
That said, a much better comparison would be with:
which can obviously be indented all sorts of ways. If one ends up needing to create filtered sublists a fair amount the original Java code will be painfully redundant, whereas if it is used once (as in this article), then it is fine. Otherwise the correct comparison is between ListUtils.filter with and without closures.
- public List<Item> bought(final User user) {
- return ListUtils.filter( items,
- new AcceptFilter() {
- public boolean accept(Item item) {
- return user.bought(item);
- }
- }
- );
- }
Jeroen Wenting replied on Tue, 2008/05/27 - 12:46am
If it were closures you'd pass just the method as an argument, not the class it comes from. And that would be far harder to read and especially debug.
jkff replied on Thu, 2008/07/03 - 3:23pm
I recently wrote an article that adresses the issues of readability of functional programs in java; you might have a look at it here: of the issues it addresses is exactly about refactoring code like the snippet above, with new AcceptFilter(), for readability and modularity.