在对我尝试使用的各种事件做出反应的 Perl 守护进程中空对象模式 http://en.wikipedia.org/wiki/Null_Object_pattern在 2 种情况下,通过创建匿名子例程,它应该只返回值 1 又名“true”(请滚动到右侧查看check子程序LOGIN and ALIVE事件):
package User;
our %EVENTS = (
LOGIN => {handler => \&handleLogin, check => sub {1}, },
CHAT => {handler => \&handleChat, check => \&mayChat, },
JOIN => {handler => \&handleJoin, check => \&mayJoin, },
LEAVE => {handler => \&handleLeave, check => \&mayLeave, },
ALIVE => {handler => sub {}, check => sub {1}, },
BID => {handler => \&handleBid, check => \&checkArgs, },
TAKE => {handler => \&handleTake, check => \&checkArgs, },
# .... more events ....
);
sub action($$$) {
my $user = shift;
my $event = shift;
my $arg = shift;
my $game = $user->{GAME};
unless (exists $EVENTS{$event}) {
print STDERR "wrong event: $event\n";
return;
}
my $handler = $EVENTS{$event}->{handler};
my $check = $EVENTS{$event}->{check};
return unless $user->$check->($arg); # XXX fails
$user->$handler->($arg);
}
sub mayChat($$) {
my $user = shift;
return if $user->{KIBITZER};
}
# ...... more methods here ...
1;
不幸的是我收到运行时错误LOGIN event:
Can't use string ("1") as a subroutine ref while "strict refs" in use
请问有人知道如何修复这里吗?
如何向匿名 Perl 子例程提供“函数指针”?
The 处理程序 => \&sub { 1 }也不这样做。
在 CentOS 5.x 和 6.x 上使用 perl 5.8.8 和 perl 5.10.1
UPDATE:
我也尝试过以下操作:
my $check = $EVENTS{$event}->{check};
return unless $check->($user, $arg);
但这没有帮助。我认为这排除了一些答案中建议的“缺失的祝福”。
更新2:
我在原来的问题中扩展了源代码片段。背景是:我正在重构我的源代码,因此我创建了%EVENTS哈希如上所列,这样对于每个传入的event(通过 TCP 套接字发送的字符串Flash 客户端 http://apps.facebook.com/video-preferans/)有一个子程序的引用(check)验证事件和对另一个子例程的引用(handler)执行一些操作。我不确定其他子程序是否有效 - 我已经卡在第一个子程序了LOGIN event.
我也不明白为什么不检查=>子{1}以上工作 - 不是sub应该返回对匿名子例程的引用(当省略名称时 - 根据perldoc perlref http://perldoc.perl.org/perlref.html第 4 节)?
更新3:
的输出打印转储器(\%事件) -
$VAR1 = {
'PLAY' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'JOIN' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'OVER1' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'ALIVE' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'DISCARD' => {
'check' => $VAR1->{'PLAY'}{'check'},
'handler' => sub { "DUMMY" },
},
'MISS1' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'LOGIN' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'TAKE' => {
'check' => $VAR1->{'PLAY'}{'check'},
'handler' => sub { "DUMMY" },
},
'ONEMORE' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'OVER2' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'MISS2' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'EXACT' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'TRUST' => {
'check' => $VAR1->{'PLAY'}{'check'},
'handler' => sub { "DUMMY" },
},
'LEAVE' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'DEFEND' => {
'check' => $VAR1->{'PLAY'}{'check'},
'handler' => sub { "DUMMY" },
},
'OPEN' => {
'check' => $VAR1->{'PLAY'}{'check'},
'handler' => sub { "DUMMY" },
},
'REVEAL' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'CHAT' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'DECLARE' => {
'check' => $VAR1->{'PLAY'}{'check'},
'handler' => sub { "DUMMY" },
},
'BACK' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'MISERE' => {
'check' => sub { "DUMMY" },
'handler' => sub { "DUMMY" },
},
'BID' => {
'check' => $VAR1->{'PLAY'}{'check'},
'handler' => sub { "DUMMY" },
}
};