Groovy – One Language to Rule Them All ?

To do what Groovy does in the .NET world, you need C#, VB.NET, Boo, F# and IronPython or IronRuby – an every one of these comes with its very own syntax !
I have programmed in 6502/680×0/80×86 assembler, C/C++, Java, C#, PHP, JavaScript, Visual Basic, Pascal, (Iron)Python, Occam, etc – and I find Groovy so appealing since:

  1. It uses a C-style syntax (inherited from Java): This world does need another computer language syntax as much as it needs global warming – so anyone not using something along the line of C/C++/Java/C#/JavaScript better have a very good reason to do so…
  2. You can do everything with it – there is no need to use another language for any task
  3. (Nearly) everything in Groovy is elegant, follows the same design principle and is as concise as possible
  4. The tons of features it offers above Java (see below), while staying a 100% compatible with it

Technical Executive Overview

Groovy is for:

  1. Statically compiled, Java-like low level programming
  2. Dynamic programming
  3. Functional programming
  4. DSL (Domain Specific Languages) generation
  5. Easier (unit) testing & mocking
  6. while being 100% Java compatible

Technical Overview

  1. Dynamic language…
  2. …that can be statically compiled if needed (@CompileStatic annotation; can also do more than syntax checking in Java, e.g. check SQL in string parameter for validity)
  3. Not unecessarily “everything goes” dynamic (as in JavaScript): Only objects of type Expando automatically add properties to their instance on assignment
  4. Same performance as Java (used to be slow in early releases, now even fully dynamic Groovy is very fast; invoke dynamic support in Java 7)
  5. Compiles to Java bytcode
  6. 100% Java interopatibility (use Java classes from Groovy / Groovy classes from Java, including subclassing, without any restrictions; Groovy collections are Java collections)
  7. 99% Java source code compatibility: Valid Java is valid Groovy in all but the most exoctic edge cases (in which case there is always a better Groovy alternative to the Java construct)
  8. Existing Java knowledge enables one to immediately get started writing Groovy code, using new features as one goes along
  9. Fully object oriented (everything is an Object)
  10. Automatic properties => every object is a bean (no getter/setter boilerplate code)
  11. Very active development: Language improvements/extensions every few months instead of every few years as in Java (while keeping backwards compatibility)
  12. Can also be used as a scripting language => no need to use a different language for these tasks (scripts are much cleaner than e.g. Perl, or awk-littered shell scripts)
  13. Functional language features: Closures, currying, etc
  14. Native list/map literal syntax: [a, b, c] / [ah:a, be:b, ce:c]
  15. Closures are much more elegant and more powerful than their Java 8 counterparts (access to all variables of surrounding scope)
  16. Default closure parameter: it  (  [1,2,3,2,4,12].findAll { it%2 == 0 }  // [2,2,4,12]  )
  17. Domain Specific Languages generation is a declared Groovy design goal
  18. Abstract syntax tree (AST) transformations support
  19. Tons of useful annotations that apply AST transformations to annotated classes
  20. Powerful string support (strings with embedded objects (GString class, e.g. “today is the ${new Date()}”, autoconverted to String as required), multiline strings, strings which can contain double quotes)
  21. Regular expression support (/…/ regex containing string, ~/…/ Pattern, =~ Matcher,   ==~ regex-equality)
  22. Operator overloading (e.g. use stream operator as in C++ to add something to a builder: builder << x << y << z )
  23. Powerful GDK library which extends nearly all JDK classes/interfaces with improved features ( List#find, String#padLeft, etc )
  24. Mixin / delegate / trait support to get around single table inheritance restrictions, while avoiding the diamond problem
  25. Native XML support ( build / consume )
  26. Native JSON support ( build / consume )
  27. Parentheses around method arguments are optional (useful for DSLs an
  28. Terminating last command in line with a semicolon is optional (more readable code due to less clutter)
  29. Elvis operator: x ?: y // x if  x not null or false, y otherwise
  30. Safe navigation (chaining):  x0?.x1?.x2?.x3 // gives null if any result in the chain is null
  31. Range support:  (0..<100).collect() // [0,1,2,…,99]
    (1..100).collect // [1,2,3,…,100]
  32. Groovy equality operator (==) is much better / more practical than Java’s
  33. Groovy has built in parallel programming support (GPars)
  34. Some powerful frameworks are written in Groovy (and therefore play best or even require Groovy):  Grails, Griffon, etc
  35. etc etc – Groovy is huge, I still learn/try new things all the time

Some quick examples I use all the time

  1. Properties are much more elegant than Java’s get/set
    1. o.x = 3  // Java: o.setX(3)
    2. println o.x  // Java: System.out.println(o.getX())
    3. o.@x  // explicitely access the underlying field member (very rare requirement)
  2. Collection processing with Groovy is fun
    1. list.each { println it } // prints each element of list on ist own line
    2. [“Franz”,”Max”,”Hubert”].collect { “My name is $it” }.join(“, “)  //  “My name is Franz, My name is Max, My name is Hubert”
  3. Map#withDefault (Note: [:] is an empty HashMap)
    1. final m = [:].withDefault { 0 }; (0..2).each { m[“x”]++; m[123]++ }; m  //  [x:3, 123:3]
    2. final m = [:].withDefault { it*2 }; m[3]++; m[7]++; m  // [3:7, 7:15]
  4. @Memoized annotation: Methods annotated with Memoized automatically cache their return values (min/max numbers of results can be given)
    1. @Memoized BusinessObject getSingleton() {  …  }  // Initialized once, all later calls return same cached object instance
    2. @Memoized(maxCacheSize = 256) int veryExpensiveToCalculateEncryptionParam(final int seed) {  …  }  // Result for each seed will be cached, max cache size = 256 entries
  5. If the last argument of a method is a Closure, it can can be appended outside of the call argument brackets; e.g.
  • void processDbRows(int maxNrRowsToProcess, String querySql, Closure processRowCls) { … }  // method definition
  • processDbRows(100, “select * from PERSON”) {  GroovyRowResult row -> println “$row.zuname, $row.vorname ($row.age)”  }  // very natural looking syntax: Closure looks like for/while/etc loop body
  • processDbRows(100, “select * from PERSON”) {  println “$it.zuname, $it.vorname ($it.age)”  }   // same as above with implicit “it” closure parameter; due to Groovy’s dynamic nature, SQL query row result members (ZUNAME, VORNAME, AGE) can be accessed using dot-notation

Links

http://www.groovy-lang.org/
http://docs.groovy-lang.org/latest/html/documentation/#_introduction
https://en.wikipedia.org/wiki/Groovy_(programming_language)

Note: When googling for “Groovy”, make sure to take into account how old an article/post is – Groovy is not Java, which changes more along the lines of decades (which has its reasons, of course, but is still a fact). The early Groovy (anno Domini 2003) was slow and a purely dynamic language…

Leave a Reply

Your email address will not be published. Required fields are marked *

*