Reputation: 1129
I am using Groovy to write a DSL handling BASIC and I would like some assistance with how to handle multi (more than 2) dimensional arrays.
I am dealing with BASIC code like this:
100 LET X = A(1, 2, 3)
It is easy to handle the 1 dimensional case - just create a closure (via MOP) that returns the elements of A, while for 2 dimensions I can do the same in the form
A(2, 3) == A.get(2)[3]
But how do I handle arrays of unlimited dimensions?
Update: To make this a bit clearer, the question is how can I return the array values dynamically in the DSL context? The script interpreter sees A(1, 2, 3) as a function call which I can intercept using the MOP. But how do I return the value of the array element in that context?
Upvotes: 3
Views: 1832
Reputation: 1129
In the end I decided to parse the input and use that to build a closure via the MOP:
/* array references look like functions to Groovy so trap them */
BinsicInterpreter.metaClass."$varName" = {Object[] arg ->
def answer = "package binsic; $varName"
arg.each {
answer = answer + "[$it]"
}
def something = shell.evaluate(answer)
return something
}
So if we had:
100 LET X = A(10, 20, 3)
The MOP traps A(...) as a function call and the code above gives me A[10][20][3]
Upvotes: 1
Reputation: 19219
If you a n-dimensional array modelled with nested lists (not the most memory-efficient way to do it, but quite easy to implement), and want to access the element at indexes [i_1, i_2, ... , i_n]
you can do:
def getElementAt(arr, ... indexes) {
indexes.inject(arr) { a, ind -> a[ind] }
}
// A 2x2x3 array implemented with nested lists.
def arr = [[[1,1,1], [1,1,5]], [[1,1,1], [1,1,1]]]
// I want to get that 5!
assert getElementAt(arr, 0, 1, 2) == 5
// The line above is equivalent to:
assert arr[0][1][2] == 5
The inject
lets you iterate a collection and accumulate the result of a given operation starting with an initial value. In this case, we iterate the indexes we want to get from the array and start the iteration with the whole array; each iteration then returns the sub-array at a given index, which is the value that will be used in the next iteration. If you happen to use it with less indexes than expected, it will return a list instead of an integer, e.g. getElementAt(arr, 0, 1) == [1, 1, 5]
.
Upvotes: 2