5

Rebol 3 で関数のディスパッチャーを作成しようとしています。これにより、プログラムが受け取る文字列ごとに、呼び出される関連関数が存在します。

例えば:

handlers: make map! [
  "foo" foo-func
  "bar" bar-func
]

ここでfoo-funcbar-funcは関数です:

foo-func: func [ a b ] [ print "foo" ]
bar-func: func [ a b ] [ print "bar" ]

アイデアはselect、文字列から始まる関数に対するものなので、次のようになります。

f: select handlers "foo"

そのため、実行fは実行と同じであり、いくつかの引数を指定してfoo-func呼び出します。f

f param1 param2

の単語を引用するmap!か、get-words を使用しようとしましたが、成功しませんでした。

aget-word!を通過せずにコンソールでa を使用すると、次のmap!ように機能します。

>> a: func [] [ print "Hello world!" ]
>> a
Hello world!
>> b: :a
>> b
Hello world!

どんな助けでも感謝します。

4

4 に答える 4

5

select handlers "foo"単語のみを取得しますfoo-func:

f: select handlers "foo"
probe f   ;will get: foo-func

そのコンテンツを取得する必要があります。

f: get f
f 1 2    ;will print "foo"

またはよりコンパクト:

f: get select handlers "foo"
于 2014-03-25T14:18:27.870 に答える
4

関数を参照する単語ではなく、実際に関数への参照をマップに含める方が適切です。単語を保存する場合は、次のように、その関数への参照を持つオブジェクトに単語がバインドされていることを確認する必要があります。

handlers: object [
    foo-func: func [ a b ] [ print "foo" ]
    bar-func: func [ a b ] [ print "bar" ]
]

handler-names: map [
    "foo" foo-func
    "bar" bar-func
]

apply get in handlers select handler-names name args

ただし、マップに関数への参照があるだけの場合は、二重間接を行う必要はなく、コードは次のようになります。

handlers: map reduce [
    "foo" func [ a b ] [ print "foo" ]
    "bar" func [ a b ] [ print "bar" ]
]

apply select handlers name args

コードがよりクリーンになり、効率も向上します。または、十分に注意している場合は、次のようになります。

handlers/(name) a b

上記のパス メソッドは、ハンドラーがない場合にコードで何もしないようにする場合にも機能します。これは、GUI などのオプションのハンドラーがある場合に一般的です。

異なるキー名を持つ同じ関数への参照を複数持つこともできます。関数を単語に割り当てる必要はありません。単語は単なる値です。path メソッドを使用して、最初にハンドラーを収集し、reduce.

handlers: make map! 10  ; preallocate as many entries as you expect
handlers/("foo"): func [ a b ] [ print "foo" ]
handlers/("bar"): func [ a b ] [ print "bar" ]
handlers/("baz"): select handlers "bar"  ; multiple references

このパス構文は を呼び出すもう 1 つの方法ですがpoke、それを好む人もいます。(できれば一時的な) 構文の競合のため、文字列値を括弧内に配置する必要がありますが、これらの括弧内では文字列キーが機能します。do selectorのより高速な代替手段pokeです。

于 2014-03-25T19:30:33.103 に答える