Perl 中动态调用子例程
我对以下内容有点困惑:
我有一个以以下方式调用子例程的函数:
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}();
}
,其中参数类似于“one_subroutine”,与可用的文件名匹配。
由于每个子例程在调用中都会接收 $self ,因此我应该通过 $self->something(); 来调用该例程。
我尝试过 $self->$routine->{$param}() 、 $self->${routine->${param}}() 和许多其他方法但没有成功。我已经检查了掌握perl的第9章“动态子例程” ,以及 与 perl 类似的问题僧侣,但我仍然无法弄清楚如何以表示 $self->updateAnotherOneSub() 的方式引用子例程,或者类似的方式让 $self 在这些子例程中被读取为参数。
预先感谢,凯伯。
I'm a bit messed up with the following:
I have a function that calls subroutines in the following way:
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'";
}
I have to change this to let each subroutine be coded in its own file, include all available files, and automagically call the subroutine inside.
I did this in a test file with the following code:
# 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}();
}
where param is something like "one_subroutine", that matches with a filename available.
Since each subroutine receives $self in the call, I should call the routine by $self->something();
I've tried $self->$routine->{$param}() , $self->${routine->${param}}() and many other things without success. I've checked chapter 9 "dynamic subroutines" of mastering perl, and a similar question to perl monks, but I can't still figure out how to reference the subroutine in a way that represents $self->updateAnotherOneSub() , or something similar that lets $self be read as a param in those subroutines.
Thanks in advance, Keber.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这看起来有点像 X/Y 问题。你到底想做什么?如果是为了减少加载时间,那么您可能会对 AutoSplit/AutoLoader 这样的模块感兴趣。
如果要创建某种子例程的数据结构,您应该将匿名子例程安装到哈希中,而不是给它们提供所有名称。
给定一个子例程引用:
您可以将其称为:
如果您有一个子例程名称,您可以查找 coderef:
如果成功(检查它),那么您可以使用
$self->$code(. ..)
来调用它。给定以下代码:
您可以将
$self
传递给例程:或者您可以按照我上面使用
can
的方式处理它:如果您不想关闭
严格的“参考”
This seems a bit like an X/Y problem. What exactly are you trying to do? If it is to reduce loading time, then modules like AutoSplit/AutoLoader might be of interest to you.
If it is to create some sort of data structure of subroutines, you should be installing anonymous subs into a hash, rather than giving them all names.
Given a subroutine reference:
you would call it as:
If instead you have a subroutine name, you can lookup the coderef:
and if that succeeds (check it), then you can use
$self->$code(...)
to call it.Given this code:
You would pass
$self
to the routine with:Or you could approach it the way I did above with
can
:if you don't want to turn off
strict 'refs'
首先尝试提取方法名称,然后它应该可以工作。我做了一个小测试脚本,可能会做一些像你想做的事情,所以:
你可以而且当然应该检查,是否存在所需的方法,就像埃里克所说:
这里重要的部分是,你提取方法名称,这样你就拥有了它在单个变量中;否则 Perl 不会为你解决这个问题 - 据我所知,没有办法设置括号或大括号来做到这一点。
Try to extract the method name first, then it should work. I did a small test script that may do something like you want to, so:
You can and of course should check, if the desired method exists like Eric said:
The important part here is, that you extract the method name so you have it in a single variable; otherwise perl won't figure that out for you - and as far as I know there is no way of setting parens or braces to do so.