Reputation: 7731
I ran into something strange when doing some data-driven testing in Groovy. If it matters, this is inside a Spock test.
Here is the way, I think, that lists are supposed to work:
def list = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
println list[0]
produces:
[1, 2, 3]
I accidentally did something like this:
def whut = [[1, 2, 3]
[4, 5, 6]
[7, 8, 9]]
println whut[0]
println whut
which outputs:
[null, null, null]
[[null, null, null]]
OK, I can see that Groovy did not like the declaration without the commas - but it compiles, so what is this?
Here's what really throws me about this syntax:
def inputz = [
[1, 0.631226308, 0.631226308, 0.631226308, 1, 0, 0.240426243]
[1, 0.312284518, 0.312284518, 0.312284518, 1, 1, 1 ]
[3, 0.823506476, 0.31230335, 0.631237191, 1, 1, 0 ]
[4, 0.934875788, 0.486395986, 0.66732053, 3, 2, 0.927654169]
[4, 0.699869773, 0.234328294, 0.424739329, 3, 3, 1 ]
]
println inputz[0]
println inputz
yields the following:
[0.631226308, 1, 1, 1, 1, 1, 1]
[[0.631226308, 1, 1, 1, 1, 1, 1]]
I'm completely lost here - what is the Groovy construct I'm creating, and why does it output these seemingly random values from my lists?
Thanks, and if you think of a more descriptive name for my question, I'll change it.
Upvotes: 8
Views: 168
Reputation: 171114
So
def whut = [[1, 2, 3]
[4, 5, 6]
[7, 8, 9]]
Creates a list [1,2,3]
, accesses the elements 4, 5 and 6 (which don't exist) to give you a list of three nulls, then accesses element 7,8 and 9 of this list of nulls (again three nulls are returned)
It then wraps this list of three nulls in a list
With this example:
[1, 0.631226308, 0.631226308, 0.631226308, 1, 0, 0.240426243]
[1, 0.312284518, 0.312284518, 0.312284518, 1, 1, 1 ]
....
it drills down to:
[1, 0.631226308, 0.631226308, 0.631226308, 1, 0, 0.240426243]
[1, 0, 0, 0, 1, 1, 1]
To give the 1st, 0th, 0th, 0th, 1st, 1st and 1st and ends up with
[0.631226308, 1, 1, 1, 0.631226308, 0.631226308, 0.631226308]
so on and so forth.
Upvotes: 10
Reputation: 17586
Breaking this down into a smaller example (in groovysh):
> [[1,2][3,4]]
===> [[null, null]]
But we don't need the extra array, so we can unwrap this:
> [1,2][3,4]
===> [null, null]
This is actually a kind of list indexing, which normally looks like this:
> [1,2][1]
===> 2
But if we index off the end of the array:
> [1,2][2]
===> null
It turns out, groovy supports slicing as part of this syntax (see http://groovy-lang.org/groovy-dev-kit.html#Collections-Slicingwiththesubscriptoperator for more examples), so we can do:
> [1,2,3][2,0]
===> [3, 1]
To get the 3rd element followed by the first element.
But combining these two facts:
> [1,2][3,4]
===> [null, null]
We're indexing past the end of the array again, but with a slice, giving us two nulls.
Upvotes: 6