qod*_*nja 3 perl hash function callback dynamic-function
我想调用一个动态调度其他函数的主控制器函数,如下所示:
package Controller;
my %callback_funcs = ();
sub register_callback{
my ($class,$callback,$options) = _@;
#apppend to %callback_funcs hash ... ?
}
sub main{
%callback_funcs = ( add => 'add_func', rem => 'remove_func', edit => 'edit_func');
while(<STDIN>){
last if ($_ =~ /^\s*$/);
if($_ == 'add' || _$ == 'rem' || _$ == 'edit'){
$result = ${callback_funcs['add']['func']}(callback_funcs['add']['options']);
}
}
}
sub add_func{
...
}
Run Code Online (Sandbox Code Playgroud)
一个警告是sub在其他模块中定义,所以回调必须能够引用它们...而且我很难让哈希正确!
mas*_*onk 11
因此,可以使用包含可以从stdin调用的匿名子例程的哈希.
my %callbacks = (
add => sub {
# do stuff
},
fuzzerbligh => sub {
# other stuff
},
);
Run Code Online (Sandbox Code Playgroud)
您可以在哈希中插入更多哈希值:
$callbacks{next} = sub {
...
};
Run Code Online (Sandbox Code Playgroud)
你会调用这样一个
$callbacks{next}->(@args);
Run Code Online (Sandbox Code Playgroud)
要么
my $coderef = $callbacks{next};
$coderef->(@args);
Run Code Online (Sandbox Code Playgroud)
您可以从STDIN或其他任何地方获取哈希键.
您也可以不明确地定义它们,然后引用它们.
sub delete {
# regular sub definition
}
$callbacks{delete} = \&delete;
Run Code Online (Sandbox Code Playgroud)
但是,我不打算称这些回调.回调是在另一个子例程返回后调用的子函数.
您的代码也充斥着语法错误,这可能会掩盖这里的深层问题.我还不清楚你在尝试使用第二级数组做什么.你什么时候定义这些潜艇,谁在什么时候使用它们?
也许这个简化的例子将有助于:
# Very important.
use strict;
use warnings;
# Define some functions.
sub multiply { $_[0] * $_[1] }
sub divide { $_[0] / $_[1] }
sub add { $_[0] + $_[1] }
sub subtract { $_[0] - $_[1] }
# Create a hash of references to those functions (dispatch table).
my %funcs = (
multiply => \&multiply,
divide => \÷,
add => \&add,
subtract => \&subtract,
);
# Register some more functions.
sub register {
my ($key, $func) = @_;
$funcs{$key} = $func;
}
register('+', \&add); # As above.
register('sum', sub { # Or using an anonymous subroutine.
my $s = 0;
$s += $_ for @_;
return $s;
});
# Invoke them dynamically.
while (<>){
my ($op, @args) = split;
last unless $op and exists $funcs{$op}; # No need for equality tests.
print $funcs{$op}->(@args), "\n";
}
Run Code Online (Sandbox Code Playgroud)
关于如何构建调度表并在单个文件中通过它调用函数的问题,您已经有了一些不错的答案,但是您仍然在谈论希望在其他模块中定义函数。如果是这样,那么基于每个模块表示的可调度功能动态地构建调度表,而不是不必担心手动使其保持最新状态会更好吗?当然可以!
演示这当然需要多个文件,而且我正在使用CPAN的Module :: Pluggable查找提供功能定义的模块。
dispatch_core.pl:
#!/usr/bin/env perl
use strict;
use warnings;
my %dispatch;
use lib '.'; # a demo is easier if I can put modules in the same directory
use Module::Pluggable require => 1, search_path => 'DTable';
for my $plugin (plugins) {
%dispatch = (%dispatch, $plugin->dispatchable);
}
for my $func (sort keys %dispatch) {
print "$func:\n";
$dispatch{$func}->(2, 5);
}
Run Code Online (Sandbox Code Playgroud)
DTable / Add.pm:
package DTable::Add;
use strict;
use warnings;
sub dispatchable {
return (add => \&add);
}
sub add {
my ($num1, $num2) = @_;
print "$num1 + $num2 = ", $num1 + $num2, "\n";
}
1;
Run Code Online (Sandbox Code Playgroud)
DTable / MultDiv.pm:
package DTable::MultDiv;
use strict;
use warnings;
sub dispatchable {
return (multiply => \&multiply, divide => \÷);
}
sub multiply {
my ($num1, $num2) = @_;
print "$num1 * $num2 = ", $num1 * $num2, "\n";
}
sub divide {
my ($num1, $num2) = @_;
print "$num1 / $num2 = ", $num1 / $num2, "\n";
}
1;
Run Code Online (Sandbox Code Playgroud)
然后,在命令行上:
$ ./dispatch_core.pl
add:
2 + 5 = 7
divide:
2 / 5 = 0.4
multiply:
2 * 5 = 10
Run Code Online (Sandbox Code Playgroud)
现在,添加新功能就像将一个带有适当dispatchable子项的新文件放入DTable目录一样简单。无需触摸dispatch_core.pl即可再次添加新功能。
编辑:响应评论中是否可以不使用Module :: Pluggable就可以完成此操作的问题,下面是经过修改的dispatch_core.pl,除了定义可调度功能的模块外,该模块不使用任何外部模块:
#!/usr/bin/env perl
use strict;
use warnings;
my %dispatch;
my @dtable = qw(
DTable::Add
DTable::MultDiv
);
use lib '.';
for my $plugin (@dtable) {
eval "use $plugin";
%dispatch = (%dispatch, $plugin->dispatchable);
}
for my $func (sort keys %dispatch) {
print "$func:\n";
$dispatch{$func}->(2, 5);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9243 次 |
| 最近记录: |