I was a bona fide Java programmer for 5 years before I started working on Aleph Point and Parse.ly. I truly believe that Python and JavaScript are fundamentally better languages than Java for a variety of reasons born out of experience with each of them. (Note: Before this gets marked as flamebait, please notice that not only was I Java programmer for more than 5 years, but I was also a Java open source contributor!) I have enormous respect for the Java open source community, which has produced some of the highest quality modules available anywhere.
Now, don’t get me wrong — Python also has batteries included, and usually, when I think that I’m missing a great module I used to use in Java, it already exists in a much more powerful form in Python’s Standard Library or the wealth of modules on PyPI, GitHub, and Bitbucket. However, I believe in not reinventing the wheel, and so if a great open source tool exists in Java, I will want to interact with it.
One of these modules which we use extensively at Parse.ly is Apache Solr, and its surrounding Lucene project modules. Lucene is an extremely mature framework for document indexing, and Solr is a powerful server-ization of that technology that fits well into complex, mixed language distributed systems. I know there are efforts — like Whoosh — to build fast search engines atop the Python language. And I applaud these efforts — more projects means more competition, and more competition means better products. However, I still believe that you go with the best of breed tools available for production software, and you try not to let religious arguments about programming language get in the way.
Lately, I have come across more and more Java open source projects that have no equivalent in Python, and which I would like to access. Knowing that I wanted to feel comfortable incorporating Java open source projects — beyond Solr, which was already nicely wrapped as a web service — I, at first, thought that I’d be forced to still live among the weeds of complex class and interface definitions, cumbersome Java IDEs, XML configuration files, and (IMO) time-wasting rabbit holes like dependency injection, configuration management, and classpath hell. And then I found Groovy.
The most under-rated language ever
Groovy was released as one of the earliest dynamic languages written atop the JVM, back in 2003. I remember hearing about it back then and not “taking it seriously”, as we programmers often do with important, new technologies. I had the same ill feelings toward JavaScript until as late as 2007, but now consider myself more a JavaScript programmer than a Java one!
In truth, had I read James Strachan’s blog post discussing why he created Groovy, I would have probably paid more attention:
So I’ve been musing a little while if its time the Java platform had its own dynamic language designed from the ground up to work real nice with existing code; creating/extending objects normal Java can use and vice versa. Python/Jython’s a pretty good base – add the nice stuff from Ruby and maybe sprinkle on some AOP features and we could have a really Groovy new language for scripting Java objects, writing test cases and who knows, even doing real development in it.
I had thoughts like these back in my Java programming days, too. I would see features that were standard in other languages — concise list/map syntax, “bare” functions (that could live outside of class definitions), optional/dynamic typing, metaprogramming, a proper REPL, first-class functions — and think to myself, “Aren’t we missing a whole lot by lacking these features in Java?” The more I started to code Python and Java side-by-side, the more I started to realize that many “core” Java technologies were basically created to cope with inadequacies of the language itself.
For example, unit testing “frameworks” and formal IDE/debuggers are more popular in Java than other languages because of the lack of the REPL — dynamic language programmers tend to test their code from an interactive shell as a regular part of programming. Utility libraries like Apache Common Utils were created to cope with syntactic deficiencies around core types like lists and maps. And on and on.
Groovy is a “post-modern language” dynamic language. By that, I mean it is clearly inspired by and learns from the lessons of both Python and Ruby. It is also the world’s first programming language that was written to target an existing community of programmers. Let me explain. Python was not written “to target” C programmers or Visual Basic programmers. It was written as a new language altogether, not targeted at anyone in particular. However, Groovy was written “to target” Java programmers — it is the dynamic language Sun should have built for the JVM as dynamic languages gained popularity and the Java language stagnated.
Groovy is respectful of and cooperative with Java itself. One of its primary design goals is to live alongside existing Java code, even while Groovy’s syntax far surpasses that of Java. In this respect, Groovy plays a very similar role in the Java ecosystem that Python plays in the C ecosystem. However, unlike Python and C’s relationship, Groovy’s relationship with Java is bidirectional. What that means is that one can easily write Java libraries that execute Groovy code (provided the Groovy Language is on the classpath as a JAR), and Groovy libraries can easily execute Java code. In fact, you can even have complex relationships among these two languages, such as Groovy classes serving as base classes for Java classes and vice versa.
However, what’s perhaps most astonishing about Groovy is that it truly got a whole lot of things right. That is, the language simply is extremely well designed, and specifically greased for programmer productivity. It learned from the mistakes of existing dynamic languages, and made a dynamic language that is truly the “best of both worlds”. When I introduced the language to an engineer on my team at Parse.ly, he uttered some words that really stuck with me: “This language was clearly designed by very, very lazy programmers.”
So true. Typing is a chore — let’s do less of it to code without sacrificing readability. That’s the Groovy way.
Over the last several years, it has matured to the point where I feel extremely comfortable writing production code in Groovy, especially thanks to the surrounding ecosystem of the Grails project.
Python is still my muse, but Groovy is my Winston Wolf
A famous character in the movie Pulp Fiction is Harvey Keitel’s “Winston Wolf”. He’s the underworld problem solver — a guy who gets things done with a no-nonsense attitude.
Winston Wolf: If I’m curt with you, it’s because time is a factor. I think fast, I talk fast, and I need you two guys to act fast if you want to get out of this.
Python is a beautiful language and will continue to be my language of choice for production code. However, I simply can’t ignore the enormous wealth of production-quality Java code that has been written for which there is no good Python equivalent. I also can’t ignore the unbelievable engineering effort that went into making the JVM a powerful, scalable, and stable platform for production software. I thought I’d have to throw this community away (for myself and my companies) due to the deficiencies of the Java language. However, I have come to realize that Groovy has proven itself the worthy successor to Java. (Yes, successor — as in, you would be a fool to write your code directly in Java these days.) And personally, I will never work on a Java project again without Groovy. Java is a mess, but Groovy is my clean-up man.
I have also observed that the “ported” JVM languages have failed. This was a surprise to me as it was happening, but in retrospect, is not as surprising. Jython and JRuby are simply not viable long-term open source projects. The target community is only those programmers who know both Python and Java or both Ruby and Java. And there was no great impetus to truly “learn” those environments, because Python programmers felt that they already “knew” Jython, since the language was the same. Is the benefit of having access to Java libraries worth the downside of using a non-standard VM for my primary programming language? Usually not.
Now, while I wasn’t even paying attention — slowly learning Groovy in my spare time and using it for small projects dependent on Java — it seems that the world of independent dynamic JVM languages has taken off. Groovy has not had nearly as much popularity as languages like Scala (used at Twitter and Foursquare) or Clojure. And Groovy lacks “sex appeal”, possibly because no significant large-scale projects have been documented atop Groovy and because the language is an incremental improvement on successful mixed-paradigm languages.
However, unlike Clojure and Scala, the Groovy language can be learned in a weekend by an existing Java programmer with dynamic language experience, and can be learned in a couple weeks by anyone else. And unlike those other languages, it does not try to be a fundamentally new programming language with new programming models. Instead, it simply dramatically improves the Java language itself using a syntax that becomes quickly familiar to dynamic programmers.
When you consider the cost/benefit analysis of learning Groovy — for a couple weeks of my time, I gain access to being able to easily script — and, with Grails, wrap as web services — an almost limitless supply of Java open source code, you realize you’d be a fool not to learn the language.
I like new stuff as much as the next guy, but Java is a language that is still used by millions of professional programmers across the world, and has proven its ability to be the basis for large projects. And Groovy is a 2X or 3X productivity improvement over Java, with full bi-directional compatibility with existing Java code? I’ll take that over a new-fangled “revolutionary” language any day!
So, what’s so groovy about Groovy?
Oh, nothing… just things like this:
["Rob", "Christopher", "Joe", "John"].findAll{ it.size() < = 4 }.each { println it } // ==> prints "Rob", "Joe" and "John" |
Yes, we’re really not in Java anymore. Let’s walk through the pain that is Java step by step to arrive at our Groovy salvation.
First, Java loves boilerplate. It really is an affliction of the language and the community. A great example of this is Java’s take on module imports.
Even though Java has a great standard library that is extremely well-designed and complete (for the most part), it fails to make this standard library easily accessible to you. That’s because all of Java’s best libraries are hidden in obtuse, deeply-nested library locations, and one can never remember where they are. IDEs solve this problem by providing an “Organize Imports” facility, which expert Java programmers use instead of managing imports themselves. This problem, alone, puts Java IDEs on significantly more productive footing than simple text editors like vim.
Groovy says, “this is nonsense — stop the madness”. In Groovy, a slew of commonly-used Java modules are simply imported automatically. If you run into a namespace conflict, that’s OK — we’re all adults here.
// these are all automatic in every Groovy module you write import java.lang.*; import java.util.*; import java.net.*; import java.io.*; import java.math.BigInteger; import java.math.BigDecimal; import groovy.lang.*; import groovy.util.*; |
Note that groovy.lang and groovy.util add significant utilities above and beyond Java.
Next up are the major data structures used by any modern programmer — lists and maps (aka dictionaries). If you haven’t been doing Java in awhile, you won’t miss this kind of code.
List<Integer> someItems = Arrays.asList(new Integer[] {1, 2, 3, 4}); for (Integer item : someItems) { System.out.println(item); } Map<String, String> someMapping = new HashMap<String , String>() {{ put("ST", "started"); put("IP", "in progress"); put("DN", "done"); }} for (Map.Entry<String, String> entry : someMapping.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " => " + value); } |
Note that the above is about the most concise possible code you can write for these operations using standard Java facilities. In fact, I have even tapped into some obscure features, using Arrays.asList to initialize the ArrayList (leveraging the fact that arrays, but not lists, have a concise initialization syntax) and leveraging double curly brace initialization for the Map, which is an extremely non-standard and perhaps even overly inefficient technique. (The alternative, though, is to write out someMapping.put(key, val) for each entry in the Map — ick).
Let’s look at this same syntax, but in Groovy.
someItems = [1, 2, 3, 4] someItems.each { println it } someMapping = ["ST": "started", "IP": "in progress", "DN": "done"] someMapping.each { key, val -> println "${key} => ${val}" } |
Not only is this code more concise, it is also much more readable. The signal-to-noise ratio is much better.
Groovy has great support for Functional Programming and Domain-Specific Languages.
// first-class functions/methods and DSL syntax clean = { text -> text.replaceAll("[^A-Za-z]*", "") } clean "my-text-*foo" remove = someItems.&remove remove 3 someItems |
It retains support for loved Java features like switch statements, but these become much more powerful and concise, e.g. in this factory function that actually returns cleaner functions depending on the passed-in type.
// proper closure, switches and variable interpolation cleanerFactory = { type -> switch (type) { case "text": return clean case "numbers": return { text -> text.replaceAll("[^0-9]*", "") } default: throw new IllegalArgumentException("invalid type ${type}") } } |
Using the cleanerFactory is a breeze, simply call it and you get back a function which you may then call. Yes, this is basically impossible in Java. To get something close, you’d have to make the factory return “Runnable” instances and then call .run() on the results.
// try/catch and bean syntax shorthand test = "my-text-*foo-1234" println cleanerFactory("text")(test) println cleanerFactory("numbers")(test) try { println cleanerFactory("foo")(test) } catch (IllegalArgumentException ex) { println "cleanerFactory returned exception: ${ex.class.simpleName}, ${ex.message}" } |
Just like Java, Groovy supports classes. But it improves them by adding a concise syntax for declaring proper JavaBeans. The following class has getters, setters, and a keyword constructor autogenerated for you.
// classes and types, if you need them class Article { String title String summary String content Date date } article = new Article( title: "Parse.ly uses Groovy, oh noes!", summary: "Didier resigns in protest", content: "Keith goes back to .Net, Toms returns to Ireland. Ahhhh!", date: new Date(2011, 3, 7) ) article.properties.each{println it} |
Also notice the special “.properties” property, which allows you to iterate over a JavaBean’s property without using Java’s obtuse reflection API.
// inheritance if you need it class WSJArticle extends Article { List topics } wsj = new WSJArticle(topics: ["US", "Finance", "World News"]) wsj.topics.each{ println it } |
Inheritance works exactly as expected, and follows Java rules.
// and sure, even call and inherit from Java code class BetterDate extends Date { def getTimeString = { return "{this.time}" } } println new BetterDate().timeString |
The interop works beautifully, too. Let’s say you want to now use BetterDate
from your Java code. You have several options available to you. The most convenient is Groovy’s “joint compiler”, groovyc, which will compile your Java code and Groovy code alongside one another, making sure all dependencies are resolved.
// and sure, use Groovy scripting constructs with existing Java APIs! lotsaItems = [1, 1, 2, 2, 2, 3, 3, 3, 3, 3] println Collections.frequency(lotsaItems, 3) Collections.shuffle(lotsaItems) println lotsaItems |
The above is an example of using existing Java APIs. Collections is surely a nice static class. Groovy lets you use it to your heart’s content.
The API for the Collections.binarySearch method is written as:
static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) |
Yes, that is “documentation” 🙂 So basically, I need to create a class that implements the Comparator interface, and then I need to pass that comparator to this method along with my list. That will require a lot of angle brackets to get the generics right. Hmm, who cares, let’s just do it the easy way: in Groovy.
// even existing, complex APIs work fine in Groovy, and with less code! comparator = [ compare: { a, b -> a.equals(b) ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } ] as Comparator println Collections.binarySearch([0, 2, 5, 7, 8], 5, comparator) |
This shows off the ability of Groovy to easily coerce values using some very intelligent rules. Comparator is an interface that expects a “compare” method — therefore, we can coerce a map with a “compare” key and a function value into an implementation of that interface.
// convenience features abound, like heredocs and safe pointer access myDocument = """ This is a long document... """ foo = [myDoc: null] println foo.myDoc?.size() // returns null rather than an exception |
If I had a dime for every time I noticed Java programmers using StringBuilder to work around its lack of multi-line strings, or adding extra methods just to do null checks… well, I’d be very rich indeed 🙂 Groovy says — no need to complicate your life with that noise.
// and type coercion that actually works! set = [1, 2, 3, 4, 5] as Set 5 in set // ==> true! |
Yes, the in keyword. Yes, lists can be converted to sets. Because that makes sense!
// this is a feature I wish Python had -- JavaScript-like map syntax map = [:] map.item1 = "foo" map.item2 = "bar" map.each { println it } // ==> "item1"="foo", "item2"="bar" println "done" |
Groovy also learns a little from JavaScript — maps are accessible using either key index or dot syntax. I personally like this, I know some Python people won’t.
// nice range and slice syntax items = [1, 2, 3, 4, 5] println items[0..2] for (i in 0..5) { println i } |
Similar to Python’s slice syntax, Groovy supports a “Range” type using two dots. It works where you expect it to: array indexing, for loops.
Using Grails, the standard web framework for Groovy, you can write simple RESTful, JSON web services in just tens of lines of code. e.g., here’s a Grails controller that renders the result of a function as JSON.
package service import com.thirdparty.library.ContentExtractor import grails.converters.JSON class ParseController { def contentExtractor = new ContentExtractor() def index = { def article = contentExtractor.extractContent(params.url) render article as JSON } } |
This will respond to a service like http://service:8080/parse?url=http://google.com with a JSON document containing the Java properties from the article object.
Seriously, how much easier can it get to wrap up a Java library as a JSON web service? Not much.
// in short, a pretty language worth looking at println "DONE." |
Download Groovy and Grails to start playing around!
—
Hi, Hacker News! (11/18/2013 – 10pm ET) There’s one discussion thread about this post and another thread about the recent Groovy 2.2 release, both sending traffic from the frontpage. Feel free to also check out some other posts I’ve written that are relevant to startups:
… or flame me on Twitter at @amontalenti!
Also, do you want to use the “Python of Python” in your everyday work? (That is: Python.) Well, Parse.ly is hiring a Senior Software Engineer, ideally in Eastern or Central Time Zone. This is a remote position for our fully distributed team.
Real nice entry, Andrew. Keep it up!
Thanks for the time-efficient tutorial, Andrew. And thanks, Jimmy, for pointing me to this.
glad you and Jimmy enjoyed it!
Thanks for this really useful article.
Nice article. Like Groovy, but speed has been a concern. Love the conciseness, but would opt for little bit more typed features like Groovy++ to speed up certain parts of the application. I used Groovy for some ETL work but speed concerns made me switch to Groovy++ and finally back to Java as the future of Groovy++ was in a bit of limbo.
The python of java is clearly scala.
Most of your examples are as concise in scala as they are in groovy (you have to prepend val however), but in addition to this you get type safety. Conciseness scala has and maybe some complexities in the type system if you want to go really deep (but which is not neccesary).
Bruce Eckel and James Strachan on Scala:
http://www.artima.com/weblogs/viewpost.jsp?thread=328540
http://macstrac.blogspot.com/2009/04/scala-as-long-term-replacement-for.html
http://macstrac.blogspot.com/2009/07/groovy-scala-example.html
Some of your examples in scala (pastable in the scala REPL):
Seq(“Rob”, “Christopher”, “Joe”, “John”).filter( _.size “started”, “IP” -> “in progress”, “DN” -> “done”)
ma
mapping.foreach{ case(k,v) => println(k+”=>”+v) }
To think a REPL is an equivalent or even a replacement of a unit testing framework is really a strange notion.
As @Kris says, Groovy speed is a concern when deploy for production.Wish groovy had lib like python had such #multiprocessing #asyncore #asynchat etc..
> Python was not written “to target” C programmers
Python made it really easy to run C-based code, perhaps one reason why it’s been successful.
> Jython and JRuby are simply not viable long-term open source projects
Dunno about Jython, but the people behind JRuby are certainly committed. Charles Nutter wrote (http://news.ycombinator.com/item?id=3372816) “invokedynamic has been a complete game-changer for JRuby”. Groovy hasn’t even begun implementing invokedynamic: there’s no trace of it in the latest “2.0-beta-2” release.
> it does not try to be a fundamentally new programming language with new programming models. Instead, it simply dramatically improves the Java language itself using a syntax that becomes quickly familiar to dynamic programmers.
If you don’t want any new programming models on the JVM, simply use Eclipse’s Xtend (http://www.eclipse.org/Xtext/xtend/). It was first released a few month’s after your post, so maybe that’s why you didn’t mention it.
> Java is a mess, but Groovy is my clean-up man.
My impression of Groovy is it’s far messier than Java. For example its grammar (http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/main/org/codehaus/groovy/antlr/groovy.g).
nice article ,but you think grails framework is better then other java framework such as spring , struts , .. , of course grails support this frameworks , but what is your opinion about grails framework ? you think it’s better if we immigrate to grails ?
Hi,
Very nice introduction. I’d like to respond to some comments I’ve read here. Regarding performance, Groovy already does a very good job for a dynamic language. In most situations, performance is not an issue because programs are I/O bound. If you do need performance because you are CPU bound, there are several available options like GPars, the most complete parallelization library available on the JVM (and not only limited to Groovy, whatever its name), writing critical parts of code in Java, wait for Groovy 2.0 static compilation mode (already testable though in early stages) or use Groovy++.
Regarding James Strachan comment, I find it unfair as James left the project *years* ago. Groovy has made an gigantic step in features, completion and performance since then, under Guillaume Laforge’s lead.
Type safety is a problem only if you don’t use the dynamic features of Groovy, that is, if you use Groovy as a better Java. If you do, take a look at groovy 2.0-beta-2 and give a try at the @TypeChecked annotation.
Last but not least, invokedynamic support *has* started, and is available in the “indy” branch of the git repository. It will probably be merged into master for the next beta. However, people often see invokedynamic as the key to performance, without even thinking about what it really means and what it implies regarding the semantics of a language…
I’ve toyed with Groovy and Ruby and Python and I have to say that Groovy feels much more *Rubyish* than Pythonic. Even the primary web framework “Grails” is a takeoff of Ruby’s “Rails”. The preponderance of Groovy Blocks also makes groovy code feel/look significantly more like Ruby than Python.
Surely it would be more accurate to title your article “the RUBY of java” ?
In fact the Groovy block syntax was lifted directly from Ruby, behold:
Groovy:
someItems = [1, 2, 3, 4]
someItems.each {
println it
}
someMapping = [“ST”: “started”, “IP”: “in progress”, “DN”: “done”]
someMapping.each { key, val ->
println “${key} => ${val}”
}
And in Ruby:
someItems = [1, 2, 3, 4]
someItems.each { |it|
puts it
}
someMapping = { ST: “started”, IP: “in progress”, DN: “done” }
someMapping.each { |key, val|
puts “#{key} => #{val}”
}
> […] Groovy, the Python of Java – Groovy is respectful of and cooperative with Java itself. One of its primary design goals is to live alongside existing Java code, even while Groovy’s syntax far surpasses that of Java. In this respect, Groovy plays a very similar role in the Java ecosystem that Python plays in the C ecosystem […]
Groovy started off as a dynamic language. After “the coup” of Dec 2005, the despots started adding static features. They added generics during 2007 after saying they weren’t going to because dynamic languages don’t need them. Last year (2010) they put in primitive types, after 7 years of calling them “leaky abstractions”. A few months ago they started adding static type checking, and saying static type compilation is coming next.
Groovy isn’t respectful of cooperative with Java: it aims to replace java as much as possible on the JVM. Sun Microsystems knew what they were up to and refused to back them for the last 5 years of its life, hence JRuby and Jython were funded but not Groovy.
@idl the Python of Java is clearly NOT Scala. Scala is a nice language, but exceedingly complex in many ways, not to mention has its warts in version dependence.
We use Groovy in production with Groovy++ speeding up some code that lends its self well.
The productivity boost from using Groovy is worth it. We manage to sling testable, well-performing code in hours instead of days. We tried Scala, but found it fit rather poorly and the type system is sometimes exceedingly complex.
Clojure is also a really nice alternative.
You guys are really funny with those Pythons, Rabbies, Scales. Groovy beats those to the ground easily. Incorporates Java API and extends upon it. Speed is great never had any issues there. If someone writes poor performing code no language will save him. Grails is bulit on top of Hibernate and Spring cant beat that. It is just natural evolution of Java. On my current project that has 2 parts 1 team of 3 programmers implements Java changes and I make corresponding changes in grails app. Guess what they’re already behind. There is only one enterprise level dynamic language/framework and thats Groovy and Grails.
Great beginning article, thanks! Of course, there’s so much more that just can’t be covered in one shot.
I’ve been using Groovy for 3+ years now, and it’s CLEARLY Java++ — i.e. Java greased for developer friendliness, performance, and elegance. It’s truly a pleasure to code with and maintain, and painful to go back to Java after a nice long session of Groovy coding.
As mentioned, the ecosystem that Groovy ties into seamlessly is a thing of beauty. The ?. syntax alone can save a developer hundreds of hours of NPE hell. GPars is the ace up Groovy’s sleeve for concurrent programming without the Java headaches.
P.S. Most likely for web developers, your Groovy/Grails app is not your end-user performance bottleneck; browser issues (JavaScript, content downloading, rendering, etc) or database issues are.
Replying regarding comment by Cedric Champeau…
> Regarding James Strachan comment, I find it unfair as James left the project *years* ago. Groovy has made an gigantic step in features, completion and performance since then, under Guillaume Laforge’s lead.
Cedric Champeau was actually employed by Guillaume Laforge at SpringSource 2 months ago to program on Groovy. He neglected to make that disclosure in his comment. He’s hardly going to say “Groovy has dribbled out the features, completion, and performance under Laforge’s lead as little as possible as late as possible”, which is closer to the truth.
In fact Champeau’s job (adding static type-checking to Groovy) was funded by moving budget away from long-time Groovy guru Jochen Theodorou in a power play by Laforge against Graeme Rocher. By diluting Theodorou’s importance to Groovy, Laforge is strengthening his position and preventing Rocher from poaching Theodorou in future.
In fact there’s no record of Champeau involvement in Groovy until a year ago. He wouldn’t know much about James Strachan, John Wilson, John Rose, Mike Spille, or any of the others burnt by their involvement with Groovy’s despotry. He’s been recruited because his technical skills surpass his political skills. When Laforge’s finished with him, he won’t know what hit him.
> Last but not least, invokedynamic support *has* started, and is available in the “indy” branch of the git repository. It will probably be merged into master for the next beta.
There’s quite a lot of “indy” branches in there. Another independent branch has a half-started Antlr 3.2 replacement for the present Antlr 2.7 parser. It was funded by Google’s “Summer of code” program last year, but after the intern finished, no-one at SpringSource continued with the work. They’ll probably apply for another worker next year (2012) to update it to Antlr 4.0 and repeat the same trick all over again, wasting more of Google’s money.
One of the most shameful sections in Groovy’s Antlr grammar treats all unicode tokens greater than 0xFF as letters:
LETTER :
‘a’..’z’|’A’..’Z’|’\u00C0′..’\u00D6’|’\u00D8′..’\u00F6’|’\u00F8′..’\u00FF’|’\u0100′..’\uFFFE’|’_’ ;
Perl, Python and Ruby at least distinguish between the different Unicode categories.
As of Geirs comments I have the feeling I should post a comment on what he said… sorry Adrew for misusing your blog for that.
Groovy is a language very much driven by user demand. At least I for my part, try to include what people tell me they wish if I think it can make sense to do so.
True we added generics. And I still say generics is a total surplus thing to do in Groovy itself. The reason why we still added it and why I am ok with it is simply, that people want to write classes in Groovy and use them from Java and there generics sometimes make sense. Till today the Groovy compiler does not a full implementation of generics. Unless you use a signature part (field type, method head, class head) Groovy simply ignores generics. And it ignores them elsewhere because we don’t intend to do type erasure or static compilation for normal Groovy.
Then about primitives…. The reason for adding them is more a political thing and you can partially thank the alioth shootout for this. People told us how slow Groovy is compared to Java. The problem is the shootout tests mostly primitive type based operations and if your language does not use primitives, then there is no way than looking bad, because the JVM does not, till at least java7, what many other VMs seem to be perfectly able to do, to handle them the same way as the wrappers. You cannot add Integers in the JVM, you have to unbox them to ints, add those and create a new Integer to box the value to finally get the result as Integer. This is horrible for performance. java7 tried to optimize the boxing/unboxing by eliminating that action if a boxing is followed by a unboxing… but that does you buy not all that much if you start with an Integer object in the first place. And imagine you have a method declared to take two primitive int doing an add and returning a primitive int. In Groovy before we had the situation that we had the arguments always as Integer, so to actually do the call we have to unbox two times. In the method, once you load the parameters, they will be boxed again… two times boxing. To actually call the plus operation we have to again 2 times unbox and box one more time. Since the method returns a primitive we had to unbox once again…. just to box again for the place the method was called… because we did only the objects. That makes 4x boxing and 5x unboxing.
You can imagine that this is horrible for the performance. My goal was then to enable a plus operation by loading the arguments as int and then execute an iadd. To make this work an int should stay an int unless needed otherwise. And unless the plus making method is called directly, which under certain circumstances can happen, we have now this situation: the arguments are loaded as int, and need to be boxed, to be then again be unboxed for the actual method call (this is only needed because our call site caching cannot handle primitives), in the method we load the parameters as int, do iadd and return the result. Again because of our callsite caching the result at the call site will be boxed. That totals to 3 times boxing and 2 times unbox, of which 2 boxing/unboxing actions can be potentially optimized away by the Java7 VM. That means we save at least 1 time boxing and 3 times unboxing. But that is only part if the gain… Now hotspot can optimize the code much more easily too.
The semantic differences caused by this are not insignificant, but small. It is now no longer possible to assign null to a primitive typed local variable, for example int. This also means the default value changed from null to 0. And before you could have done this: “int i=x; int j=i; assert i.is(j)”, which now may no longer work fully, since i and j are now different references and the method “is” is called with the boxed version of i and j. Given the improvements through primitive optimizations – if they can be used, I thought that is a small price to pay.
Then about James… back then Groovy had a static compiler already btw. when James more or less paid zero afford for the project anymore I asked him if I can remove that part, because it was by default not enabled (needed recompilation) and it was not taken care of by anybody. How much that code would have given I don’t know I never tried that. But since it didn’t use all that much type information I don’t think it helped much in the first place. Back then, when James was still the project lead Groovy was without a direction and a vision for the feature. Only once Guillaume and me formed a team I could see one. Well I hope that doesn’t sound like I want to brag. Anyway… what James did mean – imho – is not so much the beauty of Scala in the first place. It is about all the trouble he had with Groovy. James mainly lost his drive on Groovy because he had too many discussions with static guys and too much political questions to answer, instead of just doing the engineering. And Groovy is not his only experience, Jelly, the former Maven 1 XML based scripting language is also something he is heavily responsible for… and I have never seen one saying that Jelly was a good idea after he used it for a while. And judging from the state of the Groovy implementation when I joined, it makes me not wonder at all. IMHO he wouldn’t have started with Groovy back then, not because Scala is better, but because for his needs Scala is good enough and the trouble of creating your own language is not worth it then in his eyes.
Then about the antlr3.2 part. It is unfinished yes, because my – I was the tutor – GSOC student didn’t finish it. It is not a half finished parser in my eyes, it is barely the lexer, with the real work being in the rules, which are mostly missing. With that much missing you can really start from scratch without loosing all that much. And I think you understand SpringSource a bit wrong here… The guys who had to finish that, would have been either Guillaume or me. I was and am busy with primitive optimizations and invokedynamic. Guillaume has also things to work on. Since Lydia failed we had two options, continue the implementation on a later point or skip to antlr4 right away. And we decided to go with the antlr4 base, which will most probably be my job next year. We may use what she made so far for that, if it fits – I have not yet decided about that. I want to take that opportunity and clean up the grammar a lot. I think many things in there are quite surplus and only cause trouble, or are better restricted at a later point. In that context I would be grateful to know what the problem is with treating anything greater than 0xFF as letter or for what a different unicode category is needed. I am not aware of the problem atm. As for the money. The student did not pass the final evaluation so she did get only the midterm money. And there will be no GSOC student for antlr4 next year, I will do that.
Then about indy. This branch contains the invokedynamic based implementation of Groovy I am currently writing. We thought about including that in our last beta, but the implementation is still too immature and doesn’t use switchpoints yet. Without those it seems indy won’t be really faster than our current call site caching – still it is at least at about the same level already. There have been mainly issues with the build on JDK7, which is required for invokedynamic, which made me not to merge the changes yet. I will meet with Remi Forax in late January to discuss how to make the implementation better and at least then it will be part of the main branch. The major version of Groovy for 2012 will contain invokedynamic, don’t worry. invokedynamic will most probably have great impact on the future of Groovy, since we will orientate ourselves on invokedynamic about what is possible and what not. We intend to make a new MOP and that one will try to use invokedynamic to its best then. If my primopts are any measurement, then Groovy performance should increase again a lot in general and bringing now quite slow things, to the same level. For example working with EMC will not have that much of an impact on performance anymore.
Then about Cedric. We already tried once to hire someone and it failed because of the inflexibility a big company like Vmware has. We could this time make it only because we had quite a bit luck with the timing and because we used the post someone just left and rerouted some resources. I earn as much as before and I don’t see that budget has been moved away from me. It is nice to have many contributors, but some problems are too difficult to solve for a short time contribution. Another person we can depend on was absolutely required. And I am happy to have a very capable person on my side, that I can depend on now.
And finally about static type checking. In the beginning I said we want to develop Groovy by what the community wants. To me it is just fine having Groovy as a partner to Java. But it seems the many people in the community think different of this. They find it troublesome to work in Java after working in Groovy. They don’t want to switch to Java just to make something faster. For me there would not have been a need for the primitive optimizations work either, but it is difficult to argue against a benchmark in which Groovy is over 30 times slower than Java. Also static type checking or even static compilation are things that are triggered by an annotation and are not enabled by default. And I don’t have a reason to agree them being there by default till the point they allow what normal Groovy already allows. And I am quite sure that this will not happen anytime soon.
> when James was still the project lead Groovy was without a direction and a vision for the feature. Only once Guillaume and me formed a team I could see one. […] Guillaume has also things to work on.
Jochen, it was informative to read your lengthy description of Codehaus Groovy’s development. I respect your technical involvement in Groovy, and perhaps Cedric will also successfully contribute a lot, as have Paul King, Jeremy Rayner, and others.
I have issues though with what technical roles despots Guillaume Laforge and Graeme Rocher have in Groovy. Many times in IT I’ve witnessed a political/business person posing as a programmer “pair up” with a technical person and contribute very little real benefit to the project at hand. Their primary focus eventually becomes keeping themselves in a job. They are usually responsible when the project isn’t completed or accepted, but they manage to pass blame onto someone else. I suspect something similar is happening with Codehaus Groovy.
You should change your section about extending final classes. java.util.Date is NOT a final class, and for instance java.sql.Date extends it. So your sample doesn’t prove whether your statement is true or not.
Use java.lang.String instead…
@Niclas Hedman, you’re right — I’ve updated the article to remove this section. This was simply a misconception on my part.
I started one of my side projects in Grails, found static typing missing so much and had to rewrite one weeks work in Play 2.x with Scala. Groovy is not a bad language but the benefits of static typing which enables learning the APIs without having to look into examples just like that and compile time errors are the most important to me. Statically typed languages FTW!
-Ram
Great article!
One small correction about the “popularity” of Groovy vs Scala, for instance, is that to date, Groovy’s been downloaded actually 3-4x more than Scala each and every month. So although there’s perhaps less buzz lately about Groovy, it’s still downloaded and used way more than all other alternative languages combined.
> Groovy’s been downloaded actually 3-4x more than Scala each and every month.
I’m not sure how you can prove those ratios. The way you keep on saying that mantra over and over makes it sound like a laundry detergent commercial.
> So although there’s perhaps less buzz lately about Groovy, it’s still downloaded and used way more than all other alternative languages combined.
You switched from “downloaded” to “downloaded and used”. The proportion of downloaders who end up using the download is just one of many many factors you’d need to account for when proving your conclusion “used way more than all other alternative languages combined”. I don’t believe you when I look at all the clues.
Great article!
I mainly develop in Php (because of the amount of work-offers), although I’m also familiar wiith other languages, like Java, C#, and Python. Of which I prefer developing in Python the most, because of the “Low Signal to Noise level” as you call it 😉
Your article caught my attention, because I am investigating languages and frameworks providing both productivity (readability, maintainability, quality of libraries) and “traditional” SOAP/XML-capabilities, in which many developers can be found.
Php has a reasonably OK SOAP-library, and has proven its capabilities in our environment, even with its quirks. But what if you could start all over again, what would we use right now…
Python, with the Django Framework is of course very nice, but I haven’t found one SOAP-library that is really flexible, and it stays hard to find many python developers.
Therefor Groovy seems to very interesting, since it opens the world of enterprise/quality Java libraries, while making it much more maintainable development environment. Quality Java developers can also be found on the market, and I guess it shouldn’t be hard to let them develop in Groovy (if they don’t know it already).
@pixelmonkey what do you currently think about groovy; 2,5 years after you wrote this article? Have you done serious/professional development in groovy since then, or did you somehow get disappointed and permanently switched back to Python, or something else?
@Leon I do all my production work at Parse.ly in Python, and haven’t had a recent use case for Groovy, just because Java interop hasn’t been that important for me lately. I lately have been intrigued by Clojure — despite it being a functional programming language, it shares a lot of design principles with Python, and has excellent Java interop and tooling, as well. I still think Groovy is a very powerful language because of how easy it is for a Ruby/Python programmer to learn, especially if that programmer has done Java before.
@Leon BTW, I recently translated one of the examples from this blog post into Clojure and other members of the Hacker News community translated the same example into Scala & C++11. You can see that here: https://gist.github.com/amontalenti/8117294