我正在创建一个调度表:
my $dispatch = {
'do_this' => \&do_this,
'do_that' => \&do_that,
'do_something' => \&do_something,
'do_something_else' => \&do_something_else,
};
我没有为密钥和值键入相同的字符串,而是希望这样做:
my $dispatch_values = ['do_this', 'do_that', 'do_something', 'do_something_else'];
my $dispatch = generate_dispatch_table($dispatch_values);
sub generate_dispatch_table {
my $values = shift;
my $table = {};
foreach $value (@$values) {
$table{$value} = #WHAT GOES HERE?
}
return $table;
}
但我不知道如何从字符串生成子例程引用。
答案 0 :(得分:4)
只需使用\&{ $sub_name }
:
#! /usr/bin/perl
use warnings;
use strict;
sub hi { print "Hi\n" }
sub bye { print "Bye\n" }
my %dispatch = map { $_, \&{$_} } qw(hi bye);
chomp(my $action = <>);
$dispatch{$action}->();
答案 1 :(得分:1)
替代方案包括:
对于一个对象,它几乎就是你习惯的对象:
#! /usr/bin/perl
package Foo;
use warnings;
use strict;
sub hi { print "Hi\n" }
sub bye { print "Bye\n" }
sub new { bless {} }
package main;
my $dispatcher = Foo->new;
chomp(my $action = <>);
$dispatcher->$action();
当然,应该检查你是否can
做了这个动作,但我们在这里省略了一些基本的检查。
另一个好的检查是不按原样使用操作,但是如果对象中有其他非分派方法,则使用指示它可分派的前缀:
#! /usr/bin/perl
package Foo;
use warnings;
use strict;
sub do_hi { print "Hi\n" }
sub do_bye { print "Bye\n" }
sub new { bless {} }
package main;
my $dispatcher = Foo->new;
chomp(my $action = <>);
$action = "do_" . $action;
$dispatcher->$action();
唯一的区别是do_
前缀,但现在调用者无法通过调度程序调用{{1}}。否则,它是相同的 - 这个调度员将发送new
和hi
像choroba的答案。
当然,请记住,如果您传入参数,bye
是第一个参数。
通过包这样做几乎是一样的:
$self
这里,第一个参数当然是“Foo”。我们也不需要对象,因此不需要构造函数。
但是,您可以将其直接应用到原始问题中,并避免使用其他一些标记。只需删除包声明,即使在默认(主)包中也可以将#! /usr/bin/perl
package Foo;
use warnings;
use strict;
sub do_hi { print "Hi\n" }
sub do_bye { print "Bye\n" }
package main;
chomp(my $action = <>);
$action = 'do_' . $action;
Foo->$action();
更改为Foo->$action()
。但是,如果您不希望传递包名,我们只需更进一步:
__PACKAGE__->$action()
TMTOWTDI。选择对您和您的代码布局最有意义的那个。有时候我使用对象模型,有时候是另一个。