我有点搞砸了以下内容:
我有一个以下列方式调用子程序的函数:
sub someFunction {
my $self = shift;
my $type = $self->{'type'};
if($type eq 'one_subroutine') {
$self->updateOneSubroutine();
}
elsif($type eq 'another_one_sub') {
$self->updateAnotherOneSub();
}
(...)
else {
die "Unsupported '$type'";
}
我必须改变它,让每个子程序在自己的文件中编码,包括所有可用文件,并自动调用里面的子程序。
我在测试文件中使用以下代码执行此操作:
# Assume a routines subdir with one_subroutine.pm file with
sub updateOneSubroutine(){
$self = shift;
$self->doSomeThings();
(...) #my code
}
1;
test.pl
# Saves in routines hash_ref a pair of file_name => subRoutineName for each file in routines subdir.
# This will be used later to call subroutine.
opendir(DIR,"lib/routines") or die "routines directory not found";
for my $filename (readdir(DIR)) {
if($filename=~m/\.pm$/){
# includes file
require "lib/routines/$filename";
# get rid of file extension
$filename=~s/(.*)\.pm/$1/g;
my $subroutine = "update_${file}";
# camelizes the subroutine name
$subroutine=~s/_([a-z0-9])/\u$1/g;
$routine->{ $filename } = $subroutine;
}
}
{
no strict "refs";
$routine->{$param}();
}
其中param类似于“one_subroutine”,它与可用的文件名匹配。
由于每个子程序在调用中都收到$ self,我应该通过$ self-> something();
调用例程我尝试过$ self-> $ routine-> {$ param}(),$ self-> $ {routine-> $ {param}}()以及许多其他事情都没有成功。我已经检查了chapter 9 "dynamic subroutines" of mastering perl和a similar question to perl monks,但我仍然无法弄清楚如何以代表$ self-> updateAnotherOneSub()的方式引用子例程,或类似的东西让$在这些子程序中,自我被读作一个参数。
提前致谢,Keber。
答案 0 :(得分:3)
这看起来有点像X / Y问题。你究竟想做什么?如果要减少加载时间,那么您可能会对AutoSplit / AutoLoader等模块感兴趣。
如果要创建某种子例程的数据结构,则应该将匿名子安装到哈希中,而不是给它们所有名称。
给出子程序参考:
my $code = sub {...};
你会把它称为:
$self->$code(...);
如果你有一个子程序名,你可以查找coderef:
my $code = 'Package::With::The::Subroutines'->can('method_name');
如果成功(检查),那么您可以使用$self->$code(...)
来调用它。
鉴于此代码:
{
no strict "refs";
$routine->{$param}();
}
您可以将$self
传递给例程:
{
no strict "refs";
$routine->{$param}($self);
}
或者你可以像我上面can
所做的那样接近它:
'package'->can($routine->{$param})->($self)
如果您不想关闭strict 'refs'
答案 1 :(得分:0)
首先尝试提取方法名称,然后它应该工作。我做了一个小的测试脚本,可以做你想做的事情,所以:
my $method = $routine->{$param};
$self->$method->();
你可以当然应该检查,如果存在所需的方法,如埃里克所说:
if ($self->can($method)) {
$self->$method->();
}
这里的重要部分是,您提取方法名称,以便将其包含在单个变量中;否则perl不会为你解决这个问题 - 据我所知,没有办法设置parens或braces这样做。