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

时间:2016-06-24 01:51:26

标签: algorithm perl global-variables declaration

我尝试编写以下算法enter image description here

的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 个答案:

答案 0 :(得分:3)

  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 ,因此您可能会引入错误。

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

  7. 这是一个有效的(编译/运行,不一定是正确的)版本:

    #!/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