Here is a checklist of changes you'll need to make to a Groovy classic codebase to ensure compatibility with the new Groovy JSR syntax.
Safe navigation
In Classic Groovy we used to use this syntax
class Person = { String name }
y = null
println "${y->name}"
Instead of using the arrow operator for safe navigation to avoid NullPointerException, we're now using the ?. operator
Now in the JSR we use this syntax
class Person = { String name }
def y = null
println "${y?.name}"
Parameter separator in the closure syntax
This allows us to use one single token for the separator between the closure in Classic Groovy we used to use this syntax
cl = {a| ...}
cl = {|a| ...}
Now in the JSR we use this syntax
This allows us to use one single token for the separator between the closure parameters and the code in in the closure which works with arbitrarily complex parameter list expressions and default values. e.g.
def cl = {String x = "hey", int y = a|b -> println "Values are $x and $y"}
collection.each {int item -> println item}
Property keyword
- property keyword has been replaced with an annotation
class Foo {
property foo
}
class Foo {
@Property foo
}
Introduction of the 'def' keyword
For Scripts (as opposed to explicitely declared classes) the syntax is not changed, i.e. variable declarations without 'def' are still allowed, because those variables are automatically created in the script binding if they don't already exist.
Introduction of the 'as' keyword
- We can change types of objects with using the 'as' keyword,
e.g.
def d0 = new Date(2005-1900, 5-1, 7) println d0
def d1 = [2005-1900, 5-1, 8] as Date println d1
Date d2 = [2005-1900, 5-1, 9] as Date println d2
Date d3 = [2005-1900, 5-1, 10] println d3
def n1 = [ 1, 3, 5, 7 ] as int[]
println n1.class
println n1.size()
println n1.length
println n1[0]
println n1[-1]
int[] n2 = [ 2, 4, 6, 8, 10 ] println n2.class
println n2.size()
println n2.length
println n2[0]
println n2[-1]
String[] n3 = [ "a", "ab", "abc", "abcd", "abcde", "abcdef" ] println n3.class
println n3.size()
println n3.length
println n3[0]
println n3[-1]
Default access level of class members
The default access level for members of Groovy classes has changed from "public" to "protected"
Classic Groovy
class Foo {
readMe_a;
readMe_b
}
xyz = new Foo(readMe_a:"Hello",readMe_b:"World")
println xyz.readMe_a
println xyz.readMe_b
Now in JSR Groovy
class Foo {
public readMe_a;
def readMe_b }
xyz = new Foo(readMe_a:"Hello",readMe_b:"World")
println xyz.readMe_a
println xyz.readMe_b
Array creation
- no special array syntax. To make the language much cleaner, we now have a single syntax to work with lists and arrays in the JSR. Also note that we can now easily coerce from any collection or array to any array type
args = new String[] { "a", "b" }
String[] args = ["a", "b"]
def x = [1, 2, 3] as int[]
long[] y = x
- Be careful: we don't support native multi-dimensional array creation right now.
float and double notation
- float and double literals cannot start with dot. So
This is to avoid ambiguity with things like ranges (1..2) and so forth
Explicit method pointer syntax
In classic Groovy you could access method pointers automatically if there was no java bean property of the given method name.
e.g.
methodPointer = System.out.println
methodPointer("Hello World")
This often caused confusion; as folks would use a property access to find something and get a method by accident (e.g. typo) and get confused. So now we make getting a method pointer explicit as follows
def methodPointer = System.out.&println
methodPointer("Hello World")
def foo = ...
def p = foo.&bar
p(1, 2, 3)
No 'do ... while()' syntax as yet.
Due to ambiguity, we've not yet added support for do .. while to Groovy
'No Dumb Expression' rule
- no dumb expression rule, so we will catch dumb expressions (where a carriage return has broken the script). e.g.
def foo() {
def x = 1
+5 return 8
}
Markup and builders
- markup / builders will change a little, but the classic syntax still applies. Not sure of the new syntax, but we'll have some kinda start/stop syntax to denote a markup block. Maybe a keyword, like
markup (builder) {
}
builder.{
}
Strings and GStrings
- single and double quote strings can only span one line; for multiple lines use triple quotes
- heredocs removal - they are kinda ugly anyway
. If you want to use them, just use treble quote instead
def foo = """
this
is
a very
long
string on many
lines
"""
- escaping of $ inside GStrings must use \$
println 'amount is $100'
println "amount is \$100"
- A new string definition is also supported which is escaping friendly, and thus particularly friendly for regex notation:
if ('abc' =~ /.../) {}
if ('abc' ==~ /.../) {}
'abc'.eachMatch(/.../) {}
['a','b','c'].grep(/a/)
switch('abc'){
case ~/.../ : whatever
}
assert 'EUOUAE'.matches(/^[aeiou]*$/)
assert 'EUOUAE' ==~ /^[aeiou]*$/
assert 'football'.replaceAll(/foo/, "Bar") == 'Bartball'
Assertions
- assert uses comma instead of colon to delimit the two parameter form of assertion statement
assert 0 <= value : "Must be non-negative"
assert 0 <= value , "Must be non-negative"
return/break/continue semantics in closures
NOT YET IMPLEMENTED
- return/break/continue to behave inside closures like these statements work in other blocks (such as the block on a for() or while() loop. More details here
Integer division
Previously, in Groovy Classic, we used the backward slash as the integer division operator. This operator being confusing with escaping sequences was removed. So instead of \ please use the intdiv() method.
Becomes
JDK5 for loop not supported
Groovy already supports a fair number of looping mechanisms, and in Classic, both for (... : ...) and for (... in ...) were supported. For the moment, only the for (... in ...) notation is allowed.
for (e : myList) { } for (Element e : myList) { } for (e in myList) { } for (Element e in myList) { }
Exclusive range
The operator for creating ranges with the upper bound excluded from the range has changed.
Instead of:
The syntax is now:
Hi Ed
Thanks for your comments; we'll take them on board. The reason for the changes is to migrate to the JSR approved Groovy; which fixes some of the ambiguities in the language.
If you don't want to move to the JSR version of Groovy, you can stay on beta-9 or the new beta-10 which will be out soon.
Note that...