内部子例程更改的嵌套模块子例程

时间:2015-04-21 10:52:11

标签: perl perl-module subroutine

我有一个以块的形式读取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.
}

在几个循环的中间,调用&amp; initiator。我想在一个模块中使用它,我可以使用&#34;但用其他模块的其他子代替&amp; 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和使用这两个模块的脚本。

2 个答案:

答案 0 :(得分:1)

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

E.g:

variable_args ( &{$functions{'foo'}}("Mary", "Lamb"), ["more stuff"] );

不会工作,因为你正在运行&#39;它会立即发送,然后发送结果 - 无论子例程的结果是什么,它都会使你$code_ref

但是你可以创建一个匿名子,然后传递:

variable_args( sub {
                     &{ $functions{'foo'} }( "Special", "Argument", @_ ) 
                   },
               $args_to_pass{'foo'} );

我会建议你在这一点上不必要地复杂化了:)

答案 1 :(得分:1)

据我所知,你想传递一个函数(reference)作为参数。 这样的事情对你有用

# 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,因为您可能有意愿;相反,你调用它并传递 soubroutine的结果,给定参数par 给读者。