显式包名称和屏蔽同一语句中的早期声明

Explicit package name and masking earlier declarations in the same statement

我尝试编写了以下算法的 perl 版本

这是我的代码:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use diagnostics;  

    my $s1 = 'GATTACCA'; 
    my $s2 = 'AGTGGGCGGGGAGAGAGAGAGAGG'; 

    my $dist = levdist($s1, $s2); 

    sub levdist 
    { 
        my ( $seq1, $seq2 ) = (@_)[0,1]; 

        my $l1 = length($s1); 
        my $l2 = length($s2); 
        my @s1 = split '', $seq1; 
        my @s2 = split '', $seq2; 

        for (my $i = 0; $i <= $l1; $i++) { 
            my $distances->[$i]->[0] = $i; 
        } 
        for (my $j = 0; $j <= $l2; $j++) { 
            my $distances->[0]->[$j] = $j;
        }
        for (my $i = 1; $i <= $l1; $i++) {
            for (my $j = 1; $j <= $l2; $j++) {
                if ( $s1[$i-1] eq $s2[$j-1] ) {
                    my $cost = 0;
                } else {
                    my $cost = 1;
                }
                my $distances->[$i]->[$j] = minimum($distances->[$i-1]->[$j-1] + my $cost,
                                          $distances->[$i]->[$j-1]+1,
                                          $distances->[$i-1]->[$j]+ 1 )
            }
        }
        my $min_distance = my $distances->[$l1]->[$l2];
        for (my $i = 0; $i <= $l1; $i++) { my $min_distance = minimum($min_distance, my $distances->[$i]->[$l2]);
        }
        for (my $j = 0; $j <= $l2; $j++ ) {
            my $min_distance = minimum($min_distance, my $distances->[$l1]->[$j]);
        }
        return $min_distance;
    }

    sub minimum
    {
        my $min = shift @_;
        foreach ( @_ ) {
            if ( $_ < $min ) {
                $min = $_;
            }
        }
        return $min;
    }

这会引发以下错误:

    Global symbol "$distances" requires explicit package name at ./levenshtein.pl line 33.
    Global symbol "$distances" requires explicit package name at ./levenshtein.pl line 34.
    Global symbol "$distances" requires explicit package name at ./levenshtein.pl line 35. 

当我将代码更改为如下所示时:

    my $distances->[$i]->[$j] = minimum(my $distances->[$i-1]->[$j-1] + my $cost,
                                          my $distances->[$i]->[$j-1]+1,
                                          my $distances->[$i-1]->[$j]+ 1 

我收到以下一组错误:

    "my" variable $distances masks earlier declaration in same statement at
     ./levenshtein.pl line 33 (#1)
     (W misc) A "my", "our" or "state" variable has been redeclared in the
     current scope or statement, effectively eliminating all access to the
     previous instance.  This is almost always a typographical error.  Note
     that the earlier variable will still exist until the end of the scope
     or until all closure references to it are destroyed.

     "my" variable $distances masks earlier declaration in same statement at
./levenshtein.pl line 34 (#1)
     "my" variable $distances masks earlier declaration in same statement at
./levenshtein.pl line 35 (#1)

我感觉自己陷入了第 22 条军规。如果我声明变量或不声明变量,我都会收到错误消息。任何见解将不胜感激。 谢谢,

  1. 使用 my 在适当的范围内声明一个变量一次。当它超出范围时,它将被清理。

  2. 使用库函数以免重新发明轮子。 List::More

  3. 您还应该使用更好的变量名。 $i,$l1,$i1它们很难阅读,但容易引入错误。

  4. 使用范围运算符会更好,所以不要写

    for (my $i = 0; $i <= $l1; $i++) { 你可以使用 for my $i ( 0 .. $l1 ) {

  5. 但是你可能需要 (0 .. $li-1) 而不是 (0 .. $li) 因为 perl 数组默认是 0-based,所以你可能是引入错误。

  6. 我建议您编写一个测试文件来验证您的算法的结果。

这是一个有效的(compiling/running,不一定正确)版本:

#!/usr/bin/perl
use warnings;
use strict;
use diagnostics;  
use List::Util qw( min max );

my $s1 = 'GATTACCA'; 
my $s2 = 'AGTGGGCGGGGAGAGAGAGAGAGG'; 

my $dist = levdist($s1, $s2); 
print "Distance between '$s1' and '$s2' is $dist\n";

sub levdist { 
    my ( $seq1, $seq2 ) = (@_); 

    my $l1 = length($s1); 
    my $l2 = length($s2); 
    my @s1 = split '', $seq1; 
    my @s2 = split '', $seq2; 
    my $distances;
    for (my $i = 0; $i <= $l1; $i++) { 
        $distances->[$i]->[0] = $i; 
    } 
    for (my $j = 0; $j <= $l2; $j++) { 
        $distances->[0]->[$j] = $j;
    }
    for (my $i = 1; $i <= $l1; $i++) {
        for (my $j = 1; $j <= $l2; $j++) {
            my $cost;
            if ( $s1[$i-1] eq $s2[$j-1] ) {
                $cost = 0;
            } else {
                $cost = 1;
            }
            $distances->[$i]->[$j] = min($distances->[$i-1]->[$j-1] + $cost,
                                         $distances->[$i]->[$j-1]+1,
                                         $distances->[$i-1]->[$j]+ 1 )
        }
    }

    my $min_distance = $distances->[$l1]->[$l2];
    for (my $i = 0; $i <= $l1; $i++) {
        $min_distance = min($min_distance, $distances->[$i]->[$l2]);
    }
    for (my $j = 0; $j <= $l2; $j++ ) {
        $min_distance = min($min_distance, $distances->[$l1]->[$j]);
    }
    return $min_distance;
}

输出

Distance between 'GATTACCA' and 'AGTGGGCGGGGAGAGAGAGAGAGG' is 6

读一读:

perldoc -f my

perldoc List::More

perldoc Test::More