jastrachan | 22 Feb 11:30 2005

support of Java style arrays; or using Groovy arrays?

Even in Classic Groovy we've never really been able to properly support 
Java style arrays. e.g. Java supports the following syntax for variable 

int[] x = {1, 2, 3}

which is not supported in any Groovy version, and cannot really be 
supported as its ambiguous with closures. Even if we did support the 
above, it'd be a bit weird in non-static type situations as well as not 
being usable as an expression

def x = {1}			// closure or array?
methodCall( {1 } )	// closure or array?

So this kind of array initialiser is not very easy to support and even 
if we did, its not very consistent and has limited use. A much more 
groovy way would be

int[] x = [1, 2, 3]

the nice thing about this is the right hand side expression is 
definitely, clearly groovy and can be used in other circumstances too

def x = [1, 2, 3]
methodCall( [1, 2, 3] )

We could also go one step further; allowing any list expression to be 
easily coerced into an array...

int[] n = [1, 2, 3]
Cheese[] x = list.collect { it.foo }

In dynamic typing mode the following actually makes a list...

def x = [1, 2, 3]

so to mimic the above at the expression level we can use the coercion 

def x = [1, 2, 3] as Integer[]
methodCall( [1 , 2 3] as int[] )

The nice thing about the above is that this provides a simple and 
consistent way to convert lists to arrays either via typesafe variables 
or using the 'as' coercion mechanism - also the mechanism is the same 
whether the expression is statically or dynamically typed and whether 
the array contents are specified exactly at compile time (like the Java 
versions) or whether they are programmatically generated, such as by 
the result of a findAll() or collect() method.


Customer[] customers = customerList.findAll { it.name.endsWith("s") }
def customers = customerList.findAll { it.name.endsWith("s") } as 

So Java has 2 array expressions...

String[] x = {1, 2, 3}


new String[] { 1, 2, 3 }

Now we can never fully implement the old style Java array initialiser, 
as discussed above; but we could consider supporting the 'new [] { ... 
}' clause though.

The plus side of supporting half-of the Java array initialiser is that
* we keep a bit more Java heritage and avoid some possible confusion

The downside of supporting half-of the Java array initialiser is that
* we don't fully support the array initialiser and so could cause some 
possible confusion

* the new[] { ... } syntax can only be used to create a static array; 
we cannot use a list expression to create the array (such as the 
collect() method example at the top of the mail) so its of limited use; 
indeed we'll end up with 2 ways of making an array - one the Java way 
and one the groovy way

* it uses {} which opens the door to ambiguity - we've been really 
careful to avoid using {} in the language other than for blocks and 
closures - indeed many languages use {} for maps but we overloaded [] 
to avoid confusion

On balance I think I favour not supporting the old Java array syntax 
and just supporting the groovier alternative

Integer[] x = [1, 2, 3]
def x = [1, 2, 3] as int[]
methodCall( [1, 2, 3] as Integer[] )
Customer[] customers = collection.findAll { it.location == 'UK }

which is much simpler, easier to learn, is quite intuitive once you've 
learnt lists and is much more consistent - working for static & dynamic 
expressions for the contents, and working the same in both static and 
dynamically typed contexts.

The added bonus is that the language ends up being smaller (we have no 
special array initialiser syntax) and we have much less possibilities 
of ambiguity with arrays and constructors/blocks/closures/inner 

A new user to Groovy might find groovy arrays a bit surprising at 
first; but you could argue that making arrays much more like lists is 
less surprising than having various wildly different constructs for 
lists and arrays depending on the static/dynamic array construction and 
static/dynamic typing.