在以下脚本中,我@basearray
在主程序中声明和修改。在dosomething
子例程中,我访问@basearray
,将其分配给脚本本地的数组,然后修改本地副本。因为我一直在小心地只更改子例程中局部变量的值,@basearray
所以不能更改。
但是,如果我在给@basearray
子例程中分配一个值时犯了一个错误,它将被更改,并且该值在调用子例程后仍将保留。
这在第二个子例程中演示doagain
。
另外,doagain
将引用\@basearray
作为参数接收,而不是@basearray
直接访问。但是,要解决该额外的麻烦并不能提供额外的安全性。为什么要那样做呢?
有没有办法保证我不会@basearray
在任何子程序中无意中进行更改?任何一种硬质安全设备,我可以建设成我的代码,类似于use strict;
一些组合也许是my
和local
?
我是否认为答案是否定是正确的,并且唯一的解决方案是不要犯粗心大意的程序员错误?
#!/usr/bin/perl
use strict; use warnings;
my @basearray = qw / amoeba /;
my $count;
{
print "\@basearray==\n";
$count = 0;
foreach my $el (@basearray) { $count++; print "$count:\t$el\n" };
}
sub dosomething
{
my $sb_name = (caller(0))[3];
print "entered $sb_name\n";
my @sb_array=( @basearray , 'dog' );
{
print "\@sb_array==\n";
$count = 0;
foreach my $el (@sb_array) { $count++; print "$count:\t$el\n" };
}
print "return from $sb_name\n";
}
dosomething();
@basearray = ( @basearray, 'rats' );
{
print "\@basearray==\n";
$count = 0;
foreach my $el (@basearray) { $count++; print "$count:\t$el\n" };
}
sub doagain
{
my $sb_name = (caller(0))[3];
print "entered $sb_name\n";
my $sf_array=$_[0];
my @sb_array=@$sf_array;
@sb_array=( @sb_array, "piglets ... influenza" );
{
print "\@sb_array==\n";
$count = 0;
foreach my $el (@sb_array) { $count++; print "$count:\t$el\n" };
}
print "now we demonstrate that passing an array as an argument to a subroutine does not protect it from being globally changed by programmer error\n";
@basearray = ( @sb_array );
print "return from $sb_name\n";
}
doagain( \@basearray );
{
print "\@basearray==\n";
$count = 0;
foreach my $el (@basearray) { $count++; print "$count:\t$el\n" };
}
(将我的评论作为答案)保证不更改子例程中的变量的一种方法是不更改它。在子例程内仅使用词法范围的变量,并将子例程内所需的任何值作为参数传递给子例程。这是足够普遍的编码实践,即封装。
可以用来强迫自己使用封装的一种想法(主要是作为实践),是在“主”代码周围放置一个块,并将子例程放置在其外部。这样,如果您不小心引用了(以前的)全局变量,use strict
将能够完成它的工作并产生致命错误。运行前。
use strict;
use warnings;
main: { # lexical scope reduced to this block
my @basearray = qw / amoeba /;
print foo(@basearray); # works
print bar(); # fatal error
} # END OF MAIN lexical scope of @basearray ends here
sub foo {
my @basearray = @_; # encapsulated
return $basearray[1]++;
}
sub bar {
return $basearray[1]++; # out of scope ERROR
}
这不会编译,并且会产生错误:
Global symbol "@basearray" requires explicit package name at foo.pl line 15.
Execution of foo.pl aborted due to compilation errors.
我会认为这是一种训练工具,可以迫使您使用良好的编码习惯,而不必在生产代码中使用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句