4

そのため、現在、降下サイズのプログラムを Rebol 3 から Red に移行中です。このプログラムは、C ライブラリ (clang) への大きなバインディングに依存しています。Red/System のバインディング部分を書き直して、ラッパー ルーチンを介してそのコードを Red と接続しています。私が使用している現在の規則は、パラメーターとして必要であり、C コードによって返されるポインターと void ポインターを red/system 整数にキャストし、それらを Red 整数としてボックス化することです。これはかなり簡単で便利です。

生の整数にしかアクセスできないので!実際の構造体の代わりにデータを使用すると、上記の方法論を使用して、パラメーターを介してポインターを戻すことができないと思われます (ボックス化されたデータが渡される前にコピーされるため)。

では、パラメーターを介してポインターを戻すための推奨される方法論はありますか? 別名、ルーチンで参照渡しする方法はありますか?

twiddle: routine [
    arg [integer!]
    return: [integer!]
] [
    arg: 321
    test: declare struct! [
        dummy [integer!]
    ]
    test/dummy: 456
    as integer! test
]

a: 123
b: twiddle a

print a ;If I could pass by reference this would be 321
print b
4

1 に答える 1

7

あなたがそうするときtwiddle a、あなたは単語aを関数に渡すのではなく、その値を渡しています。Rebol に似た言語の単語は、他の多くの言語のように厳密には変数ではありません。それらは、名前空間とも呼ばれるコンテキスト内の他の値を参照できるファーストクラスの値です。したがって、単語は値を保持せず、値を保持するコンテキスト テーブルを指します。コンテキストを 2 つの列を持つテーブルとして描くことができます。左の列には単語が含まれ、右の列にはそれぞれの値が含まれます。

したがって、厳密に言えば、「参照渡し」はなく、Red レベルでのみを操作でき、それらの値は常にコンテキスト テーブルから Red 内部スタックにコピーされます。によって参照される値を変更する場合は、その新しい値aに設定する必要があります。aこれは、Red ランタイム API を使用して Red/System レベルでも実現できますが、その API は現在非公式であり、完全に安定化されていません (ただし、とにかく内部で頻繁に使用されています)。

ニーズに対応する良い方法の 1 つは、個々の値を単語に割り当てるのではなく、値のブロックを作成することですが、それが適切であることを確認するには、何を達成したいかを十分に知りません。

したがって、このプリアンブルの後、質問にもっと直接的に答えるために、ルーチンへの参照渡しはできません。値渡しのみが可能です (マーシャリングされた値を取得するか、stack のボックス化された値へのポインターを取得し、コンテキストではありません)。テーブル)。その値がたまたまブロックのようなシリーズだったら!たとえば、そのコンテンツをルーチンから変更できます (要素の変更、追加、削除など)。

とにかく、単語が参照する値をルーチン内から本当に変更したい場合は、次のようにします。

twiddle: routine [
    w [word!]
    return: [integer!]
    /local test
] [
    test: declare struct! [
        dummy [integer!]
    ]
    test/dummy: 456
    _context/set w as red-value! integer/box as-integer test
    as integer! test
]

a: 123
b: twiddle 'a

ご覧のとおり、期待していた副作用を実現するには、未評価の単語 (lit-word!) を渡し、ルーチンからその値を設定する必要があります。ただし、これは推奨される方法ではありません。ブロックを使用することをお勧めします。またはオブジェクト!値を Red/System レベルから Red レベルにプッシュするか、返された値を単に単語に割り当てますb

お役に立てれば。

于 2015-05-07T07:56:54.363 に答える