内部子程序发生变化的嵌套模块化子程序
Nested modular subroutines where the inner subroutine changes
我有一个分块读取 FASTA 文本文件的子程序。
sub reader {
foreach my $line (<IN>) { # read line by line
chomp $line;
if ($line =~ m/^>/) { # if it's a title
&initiator($title, $seq) unless $firsttitle == 1;
$firsttitle = 0;
($title = $line) =~ s/^>//; # title without > at start
$seq = ''; # new seq
} else {
$seq = $seq . $line; # append seq lines
}
}
&initiator($title, $seq); # Do the thing for the last seq.
}
在几个循环的中间,调用了&initiator。我想把它放在一个我可以 "use" 的模块中,但是用其他模块中的其他 sub 替换 &initiator。这些潜艇也需要有自己的输入。像下面这样的工作还是有更优雅的解决方案?
use Reader qw(reader);
use Othersub qw(subroutine);
my @par = ('Mary', 'Lamb');
my %functions = (foo => \&Othersub::subroutine);
&reader($file_to_read, $functions{'foo'}($par[0], $par[1]));
注意:最终文件结构是 Othersub.pm、Reader.pm 和使用这两个模块的脚本。
Perl 允许您创建对事物的引用,这包括子例程和数组。
如果您要传递不同的参数,那么我建议您通过数组引用而不是您正在做的事情来传递。有点像这样:
use strict;
use warnings;
sub variable_args {
my ( $code_ref, $array_ref ) = @_;
#dereference code ref;
#dereference array ref;
&$code_ref( @$array_ref, "optional", "extra", "arg" );
}
sub foo_func {
foreach (@_) {
print "Foo $_\n";
}
}
sub bar_func {
print "BAR: ", join( ":", @_ ), "\n";
}
#could inline the functions as anonymous subs. I would avoid doing that
#unless they're pretty short/clear.
my %functions = (
'foo' => \&foo_func,
'bar' => \&bar_func,
);
my %args_to_pass = (
'foo' => [ "Mary", "Lamb" ],
'bar' => [ "Some", "Fish", "Pie" ],
);
for my $thing ( "foo", "bar" ) {
variable_args( $functions{$thing}, $args_to_pass{$thing} );
}
注意 - 在上面的示例中,您调用 &initiator
。你不应该这样做。它是 Perl 4 中弃用的语法,并且是多余的(并且在某些情况下可能会产生一些不良后果)。
但我建议您这样做,而不是按照您的方式进行。你可以让它工作:
&reader($file_to_read, $functions{'foo'}($par[0], $par[1]));
但是当您尝试这样做时会发生什么,您将(可能)立即 运行 您的函数,并将其结果传递给 reader
。
例如:
variable_args ( &{$functions{'foo'}}("Mary", "Lamb"), ["more stuff"] );
不会工作,因为你会立即 'running' 它,然后发送结果 - 这将使你的 $code_ref
无论 结果如何 的子程序是。
但是你可以创建一个匿名子,然后传递:
variable_args( sub {
&{ $functions{'foo'} }( "Special", "Argument", @_ )
},
$args_to_pass{'foo'} );
不过,我建议您在这一点上变得不必要地费解了:)
据我猜测,您想传递一个函数(引用)作为参数。
这样的东西应该适合你
# Script
use Reader qw(reader);
use Othersub qw(subroutine);
my @par = .... ;
reader( $file_to_read , \&subroutine , @par);
# Reader.pm
sub reader {
my $file = shift;
my $initiator = shift;
my @par = @_;
...
$initiator->( $file , @par)
...
}
备注: 在代码的最后一行,您没有将函数 subroutine
传递给 reader
,因为您可能有意向;相反,您调用它并传递 子例程的结果,给定参数 par 到 reader。
我有一个分块读取 FASTA 文本文件的子程序。
sub reader {
foreach my $line (<IN>) { # read line by line
chomp $line;
if ($line =~ m/^>/) { # if it's a title
&initiator($title, $seq) unless $firsttitle == 1;
$firsttitle = 0;
($title = $line) =~ s/^>//; # title without > at start
$seq = ''; # new seq
} else {
$seq = $seq . $line; # append seq lines
}
}
&initiator($title, $seq); # Do the thing for the last seq.
}
在几个循环的中间,调用了&initiator。我想把它放在一个我可以 "use" 的模块中,但是用其他模块中的其他 sub 替换 &initiator。这些潜艇也需要有自己的输入。像下面这样的工作还是有更优雅的解决方案?
use Reader qw(reader);
use Othersub qw(subroutine);
my @par = ('Mary', 'Lamb');
my %functions = (foo => \&Othersub::subroutine);
&reader($file_to_read, $functions{'foo'}($par[0], $par[1]));
注意:最终文件结构是 Othersub.pm、Reader.pm 和使用这两个模块的脚本。
Perl 允许您创建对事物的引用,这包括子例程和数组。
如果您要传递不同的参数,那么我建议您通过数组引用而不是您正在做的事情来传递。有点像这样:
use strict;
use warnings;
sub variable_args {
my ( $code_ref, $array_ref ) = @_;
#dereference code ref;
#dereference array ref;
&$code_ref( @$array_ref, "optional", "extra", "arg" );
}
sub foo_func {
foreach (@_) {
print "Foo $_\n";
}
}
sub bar_func {
print "BAR: ", join( ":", @_ ), "\n";
}
#could inline the functions as anonymous subs. I would avoid doing that
#unless they're pretty short/clear.
my %functions = (
'foo' => \&foo_func,
'bar' => \&bar_func,
);
my %args_to_pass = (
'foo' => [ "Mary", "Lamb" ],
'bar' => [ "Some", "Fish", "Pie" ],
);
for my $thing ( "foo", "bar" ) {
variable_args( $functions{$thing}, $args_to_pass{$thing} );
}
注意 - 在上面的示例中,您调用 &initiator
。你不应该这样做。它是 Perl 4 中弃用的语法,并且是多余的(并且在某些情况下可能会产生一些不良后果)。
但我建议您这样做,而不是按照您的方式进行。你可以让它工作:
&reader($file_to_read, $functions{'foo'}($par[0], $par[1]));
但是当您尝试这样做时会发生什么,您将(可能)立即 运行 您的函数,并将其结果传递给 reader
。
例如:
variable_args ( &{$functions{'foo'}}("Mary", "Lamb"), ["more stuff"] );
不会工作,因为你会立即 'running' 它,然后发送结果 - 这将使你的 $code_ref
无论 结果如何 的子程序是。
但是你可以创建一个匿名子,然后传递:
variable_args( sub {
&{ $functions{'foo'} }( "Special", "Argument", @_ )
},
$args_to_pass{'foo'} );
不过,我建议您在这一点上变得不必要地费解了:)
据我猜测,您想传递一个函数(引用)作为参数。 这样的东西应该适合你
# Script
use Reader qw(reader);
use Othersub qw(subroutine);
my @par = .... ;
reader( $file_to_read , \&subroutine , @par);
# Reader.pm
sub reader {
my $file = shift;
my $initiator = shift;
my @par = @_;
...
$initiator->( $file , @par)
...
}
备注: 在代码的最后一行,您没有将函数 subroutine
传递给 reader
,因为您可能有意向;相反,您调用它并传递 子例程的结果,给定参数 par 到 reader。