这个Perl子程序有什么问题?

时间:2017-04-21 14:24:37

标签: perl subroutine

我正在尝试实现一个计算输入字符串的d邻居的子程序。这是planted motif search的一个实现的一部分,但我的问题更为笼统。这是代码:

#subroutine for generating d-neighbors
sub generate_d_neighbors{
    # $sequence is the sequence to generate d-neighbors from
    # $HD is the Hamming Distance
    my ($sequence, $HD) = @_;

    for(my $i = 0; $i=$HD; $i++){
        my @l = ['A', 'C', 'T', 'G'];
        my @t = splice(@l,$sequence[$i]);  
       #TODO
    }
}

错误发生在最后一行,说:

Global symbol "@sequence" requires explicit package name (did you forget to declare "my @sequence"?

据我所知,Perl不会像Java中那样采用subroutine(param1, param2)形式的参数,但为什么$sequence未被识别为已经初始化?

3 个答案:

答案 0 :(得分:4)

您的代码存在一些问题:

sub generate_d_neighbors{
    my ($sequence, $HD) = @_;

    for(my $i = 0; $i=$HD; $i++){
        my @l = ['A', 'C', 'T', 'G'];
        my @t = splice(@l,$sequence[$i]);  
    }
}

首先,让我们看一下

    for(my $i = 0; $i=$HD; $i++){

假设$HD非零,此循环将永远不会终止,因为条件永远不会为假。如果您希望$i的范围从0$HD,那么将该语句写为for my $i (0 .. $HD)会更好。

其次,你有

        my @t = splice(@l,$sequence[$i]);  

你似乎假设有一个数组@sequence,你正试图访问它的第一个元素。但是,$sequence是对数组的引用。因此,您应该使用

$sequence->[$i]

第三(感谢@Ikegami),你有

        my @l = ['A', 'C', 'T', 'G'];

for循环中。然后@l将包含单个元素,即对包含元素'A''C''T''G'的匿名数组的引用。相反,使用:

my @l = qw(A C T G);

我不确定您希望使用splice(@l, $sequence->[$i])确切达到什么目标,但可以更好地编写为:

 my @t = @l[0 .. ($sequence->[$i] - 1)];  

实际上,您可以将两个分配减少到:

 my @t = qw(A C T G)[0 .. ($sequence->[$i] - 1)];

答案 1 :(得分:0)

在我看来,你想要

substring($sequence, 0, 1)

而不是

$sequence[0].

在Perl中,字符串是第一类变量,而不是数组类型。

或许你想要splice(@l, $sequence->[0])

答案 2 :(得分:0)

此列表分配语法:

my (@sequence, $HD) = @_;

没有做你想做的事情(将最后一个参数放在$HD中,其余参数放在@sequence中)。数组总是占用它所能得到的所有参数,不会留下任何参数。

如果只有一个数组,则撤销订单可以正常工作:

my ($HD, @sequence) = @_;

并在调用者中进行相应的更改。

要更一般地解决问题,请使用参考:

my ($sequence, $HD) = @_;

并像这样调用sub:

generate_d_neighbors(\@foo, $bar);

或者这个:

# Note the brackets, which make an array reference, unlike parentheses
# which would result in a flat list.
generate_d_neighbors([...], 42);

如果您使用原型:

sub generate_d_neighbors (\@$)
然后调用者可以说

generate_d_neighbors(@foo, $bar);

并且@foo自动成为引用,就好像它是\@foo

如果您使用任何基于参考的解决方案,则必须根据以下规则更改函数体以使用$sequence而不是@sequence

  1. @sequence更改为@$sequence
  2. $#sequence更改为$#$sequence
  3. $sequence[...]更改为$sequence->[...]
  4. @sequence[...]更改为@$sequence[...](但请确保您真的打算使用数组切片...如果您对perl不熟悉,那么您可能并不意味着它,并且应该使用$sequence[...]代替)