3

Groovy を使用して BASIC を処理する DSL を作成していますが、多次元 (2 次元以上) の配列を処理する方法について支援が必要です。

私はこのようなBASICコードを扱っています:

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

1 次元の場合は簡単に処理できます。A の要素を返すクロージャを (MOP 経由で) 作成するだけですが、2 次元の場合は次の形式で同じことができます。

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

しかし、無制限の次元の配列をどのように処理すればよいでしょうか?

更新:これを少し明確にするために、DSLコンテキストで配列値を動的に返すにはどうすればよいですか? スクリプト インタープリタは A(1, 2, 3) を、MOP を使用してインターセプトできる関数呼び出しと見なします。しかし、そのコンテキストで配列要素の値を返すにはどうすればよいでしょうか?

4

2 に答える 2

2

ネストされたリストでモデル化された 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]

于 2012-06-15T21:35:11.880 に答える
1

最後に、入力を解析し、それを使用して 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] を返します

于 2012-06-17T21:51:55.197 に答える