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 中的单词但没有成功。

在控制台上使用 a get-word!,而不通过 amap!它可以工作:

>> 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

该路径语法只是另一种调用方式poke,但有些人更喜欢它。由于(希望是临时的)语法冲突,我们必须将字符串值放在括号中,但在这些括号中,字符串键有效。do select它是or的更快替代方案poke

于 2014-03-25T19:30:33.103 回答
4

地图中的 foo-func 只是一个未评估的词

>> type? select handlers "foo"
== word!

您应该首先创建函数,然后减少用于创建处理程序映射的块,以便

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

那么你的地图中有功能

>> type? select handlers "foo"
== function!
于 2014-03-25T14:04:58.690 回答
2

尝试: .... f: 选择处理程序“foo” ....

于 2014-03-25T14:00:19.937 回答