将二维以上的 Java 数组视为列表



我正在使用Groovy编写DSL处理BASIC,我想在如何处理多维(超过2)维数组方面获得一些帮助。

我正在处理这样的基本代码:

100 LET X = A(1, 2, 3)

处理 1 维情况很容易 - 只需创建一个闭包(通过 MOP)返回 A 的元素,而对于 2 维,我可以在表单中做同样的事情

A(2, 3) == A.get(2)[3]

但是如何处理无限维度的数组呢?

更新:为了更清楚地说明这一点,问题是如何在 DSL 上下文中动态返回数组值?脚本解释器将 A(1, 2, 3) 视为函数调用,我可以使用 MOP 拦截它。但是如何在该上下文中返回数组元素的值呢?

如果你是一个用嵌套列表建模的 n 维数组(不是最节省内存的方法,但很容易实现),并且想要访问索引处的元素[i_1, i_2, ... , i_n]你可以这样做:

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

inject允许您迭代集合并从初始值开始累积给定操作的结果。在这种情况下,我们迭代我们想要从数组中获取的索引,并从整个数组开始迭代;然后,每次迭代都会返回给定索引处的子数组,这是将在下一次迭代中使用的值。如果您碰巧使用它的索引比预期的少,它将返回一个列表而不是整数,例如 getElementAt(arr, 0, 1) == [1, 1, 5] .

最后,

我决定解析输入并使用它来通过 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
    }

因此,如果我们有:

100 LET X = A(10, 20, 3)

MOP将A(...)捕获为函数调用,上面的代码给了我A[10][20][3]

最新更新