不能在perl中定义其值不能在子例程中更改的变量?

雅各布·韦格林

在以下脚本中,我@basearray在主程序中声明和修改dosomething子例程中,我访问@basearray,将其分配给脚本本地的数组,然后修改本地副本。因为我一直在小心地只更改子例程中局部变量的值,@basearray所以不能更改。

但是,如果我在给@basearray子例程中分配一个值时犯了一个错误,它将被更改,并且该值在调用子例程后仍将保留。

这在第二个子例程中演示doagain

另外,doagain将引用\@basearray作为参数接收,而不是@basearray直接访问但是,要解决该额外的麻烦并不能提供额外的安全性。为什么要那样做呢?

有没有办法保证我不会@basearray在任何子程序中无意中进行更改任何一种硬质安全设备,我可以建设成我的代码,类似于use strict;一些组合也许是mylocal

我是否认为答案是否定是正确的,并且唯一的解决方案是不要犯粗心大意的程序员错误?

#!/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" };
}

TLP

(将我的评论作为答案)保证不更改子例程中的变量的一种方法是不更改它。在子例程内仅使用词法范围的变量,并将子例程内所需的任何值作为参数传递给子例程。这是足够普遍的编码实践,即封装。

可以用来强迫自己使用封装的一种想法(主要是作为实践),是在“主”代码周围放置一个块,并将子例程放置在其外部。这样,如果您不小心引用了(以前的)全局变量,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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么我不能在定义中定义变量?

sprintf不能在printf调用中更改静态变量

不能在 pydantic init 函数中定义变量

为什么我不能在React中更改输入值?

为什么我不能在SQLite中更改值?

不能在数据框中更改值

为什么不能在GridView中更改值?

属性值不能在javascript中未定义

为什么不能在lambda函数中更改通过复制捕获的变量的值?

为什么我不能在Timer.scheduledTimer函数中更改变量的值?

不能在子字段更新中存储

常量不能在反应中定义

能够在C中更改const的值,但不能在C ++中更改

为什么不能在IronPython中更改缓存模块中的变量?

变量不能在findOne内部更改

为什么信号不能在 Perl 的模块中捕获

不能在mousemove上更改值

为什么我不能在self是类的协议扩展中更改变量?

为什么我不能在PHP中为类变量定义连接字符串?

为什么不能在switch中定义两次变量?

为什么我不能在zsh中定义一个名为path的只读变量?

为什么我不能在Angular 2中用方括号表示法定义变量

为什么我不能在类的不同行中声明和定义成员变量?

为什么不能在Ruby的单例类定义中访问类实例变量?

<span>不能在react中显示为<select>的子级

为什么这些子数组不能在TS中渲染?

为什么不能在try / catch块中访问变量?

为什么我不能在代码中删除中间变量?

为什么我不能在变量中捕获FakeItEasy期望?