Perl 中的作用域

Scoping in Perl

作为一名生物学专业的学生,​​我正在努力扩展我的编程知识,并且 运行 遇到了 Perl 问题。

我正在尝试创建一个程序来生成 运行dom DNA 字符串并对生成的数据执行分析工作。

在程序的第一部分中,我能够打印出存储在数组中的字符串,但在第二部分中,我只能检索数组中的一个元素。

这可能是 Perl 范围规则的一部分吗?

#!usr/bin/perl

# generate a random DNA strings and print it to file specified by the user.

$largearray[0] = 0;

print "How many nucleotides for the string?\n";
$n      = <>;
$mylong = $n;

print "how many strings?\n";
$numstrings = <>;

# @largearray =();
$j = 0;

while ( $j < $numstrings ) {

    $numstring = '';    # start with the empty string;
    $dnastring = '';
    $i         = 0;

    while ( $i < $n ) {

        $numstring = int( rand( 4 ) ) . $numstring;    # generate a new random integer
                                                       # between 0 and 3, and concatenate
                                                       # it with the existing $numstring,
                                                       # assigning the result to $numstring.
        $i++;                                          # increase the value of $i by one.
    }

    $dnastring = $numstring;
    $dnastring =~ tr/0123/actg/;                       # translate the numbers to DNA characters.
                                                       #print $dnastring;
                                                       #print "\n";

    $largearray[j] = $dnastring;                       #append generated string to end of array

    #print $largearray[j];
    #print $j;
    #IN HERE THERE ARE GOOD ARRAY VALUES
    #print "\n";

    $j++;
}

# ii will be used to continuously take the next couple of strings from largearray
# for LCS matching.

$mytotal = 0;
$ii      = 0;

while ( $ii < $numstrings ) {

    $line = $largearray[ii];
    print $largearray[ii];    #CANNOT RETRIEVE ARRAY VALUES
    print "\n";

    $ii++;
    @string1 = split( //, $line );

    $line = $largearray[ii];

    #print $largearray[ii];
    #print "\n";
    $ii++;
    chomp $line;
    @string2 = split( //, $line );

    $n = @string1;    #assigning a list to a scalar just assigns the
                      #number of elements in the list to the scalar.
    $m = @string2;

    $v  = 1;
    $Cm = 0;
    $Im = 0;

    $V[0][0] = 0;     # Assign the 0,0 entry of the V matrix

    for ( $i = 1; $i <= $n; $i++ ) {    # Assign the column 0  values and print
                                        # String 1  See section 5.2 of Johnson
                                        # for loops
        $V[$i][0] = -$Im * $i;

    }

    for ( $j = 1; $j <= $m; $j++ ) {    # Assign the row 0 values and print String 2
        $V[0][$j] = -$Im * $j;

    }

    for ( $i = 1; $i <= $n; $i++ ) {    # follow the recurrences to fill in the V matrix.
        for ( $j = 1; $j <= $m; $j++ ) {

            #   print OUT "$string1[$i-1], $string2[$j-1]\n"; # This is here  for debugging purposes.

            if ( $string1[ $i - 1 ] eq $string2[ $j - 1 ] ) {
                $t = 1 * $v;
            }
            else {
                $t = -1 * $Cm;
            }

            $max = $V[ $i - 1 ][ $j - 1 ] + $t;

            #  print OUT "For $i, $j, t is $t \n"; # Another debugging line.
            if ( $max < $V[$i][ $j - 1 ] - 1 * $Im ) {
                $max = $V[$i][ $j - 1 ] - 1 * $Im;
            }

            if ( $V[ $i - 1 ][$j] - 1 * $Im > $max ) {
                $max = $V[ $i - 1 ][$j] - 1 * $Im;
            }

            $V[$i][$j] = $max;
        }
    }    #outer for loop

    print $V[$n][$m];
    $mytotal += $V[$n][$m];    # append current result to the grand total
    print "\n";

}    # end while loop

print "the average LCS value for length ", $mylong, " strings is: ";
print $mytotal/ $numstrings;

我认为您的代码中有错别字:

ii => 必须是 $ii

不要忘记将其放在代码的开头:

use strict;
use warnings;

为了避免这种(和其他)错误

这不是范围界定问题。您已经声明了 none 变量,其效果是隐式地使它们成为全局变量并且可以在您的代码中随处访问

我重新格式化了你的 Perl 程序以便我可以阅读它,然后将它添加到你的程序的顶部

use strict;
use warnings 'all';

在您编写的每个 Perl 程序中必不可少

然后我添加了

no strict 'vars';

这是一个非常糟糕的主意,让你不用声明任何变量就可以逃脱

结果是这样的

Argument "ii" isn't numeric in array element at E:\Perl\source\dna.pl line 60.
Argument "ii" isn't numeric in array element at E:\Perl\source\dna.pl line 61.
Argument "ii" isn't numeric in array element at E:\Perl\source\dna.pl line 67.
Argument "j" isn't numeric in array element at E:\Perl\source\dna.pl line 42.
Bareword "ii" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 60.
Bareword "ii" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 61.
Bareword "ii" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 67.
Bareword "j" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 42.
Execution of E:\Perl\source\dna.pl aborted due to compilation errors.

第 42 行(我重新格式化后的版本)是

$largearray[j] = $dnastring

第 60、61 和 67 行是

$line = $largearray[ii];
print $largearray[ii];    #CANNOT RETRIEVE ARRAY VALUES

$line = $largearray[ii];

您正在使用 jii 作为数组索引。这些是 Perl 子例程调用,而不是变量。添加 use strict 会阻止编译,除非您还声明了 sub iisub j

如果您只是将 jii 更改为 $j$ii,您 可能 逃脱它,但是你肯定会遇到更多问题

请对您自己的代码进行相同的更改,并声明您需要使用的每个变量my尽可能靠近它们被使用的第一个地方

您还应该改进您的变量命名。 @largearray 之类的东西毫无意义: @ 表示它是一个数组,它是否大是相对的,对理解你的代码没有多大用处。如果您对它的用途没有更好的描述,那么 @table@data 可能更好一些

同样,请避免使用大写字母和大多数单字母名称。 @V$Cm$Im 没有意义,如果这些名称更好,您将需要更少的评论

如果您正确地缩进了您的块并使它们足够短以便可以在屏幕上看到开头和结尾,那么您当然不需要像 # end while loop# outer for loop 这样的注释同时,注释越少越好,因为它们会严重扰乱代码结构

最后,值得注意的是,C 风格的 for 循环很少是 Perl 中的最佳选择。你的

for ( $i = 1; $i <= $n; $i++ ) { ... }

更清晰
for my $i ( 1 .. $n ) { ... }

并在此时声明控制变量使得无需为每个新循环发明新名称,如 $ii