2015-05-14 93 views
0

我创建一个调度表的子程序参考:生成字符串中的

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

虽然我不知道如何从字符串中生成子例程引用。

回答

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

替代品包括:

  • 使用的对象。
  • 使用套餐。

对于一个对象,这几乎是你习惯了什么:

#! /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_前缀,但现在调用者不能通过调度程序调用new。否则,它是一样的 - 这个调度员将像choroba的答案一样调度hibye

请记住,当然,如果您传递参数,$self是第一个参数。

通过包这样做几乎是一样的:

#! /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()。但是,如果你不希望有包名传递中,我们采取这只是一个很小的一步:

sub do_hi { print "Hi\n" } 
sub do_bye { print "Bye\n" } 

chomp(my $action = <>); 
$action = 'do_' . $action; 
__PACKAGE__->can($action)->(); 

TMTOWTDI。选择一个对你最有意义的代码和你的代码布局。有时我会使用对象模型,有时候会使用另一个。