【问题标题】:Globally defined array全局定义的数组
【发布时间】:2014-07-10 11:53:21
【问题描述】:

全局定义一个数组,用一个子例程填充它,然后在脚本的另一部分访问它是不好的做法吗?例如,

use strict;
use warnings;

my @people = qw( Ted Bill Tom);
my @names;

&main;

sub main{
    foreach(@people){
        &fillNames;
    }
}

sub fillNames {

    undef @names;
    print "$_\n";
    push(@names,$_);


    }

在上述情况下,我可以让子程序返回数组,但在我的程序中,我使用多个数组执行此操作(据我所知,子程序不能返回多个数组)。

我看到的另一种方法是创建一个文件,让子例程打印文件每个索引的数组内容,然后让主子例程访问该文件。这是更好的方法吗?

【问题讨论】:

  • 在使用全局数组之前,我会返回一个数组引用列表。
  • 如果要清空数组,请使用@names = ();
  • @names = get_names(); 会更好,并且还可以消除对全局的需要。
  • 简短回答:除了常量之外,不要依赖全局变量。始终传递参数和返回值。这将引导您更好地设计程序,包括更好的可读性和可维护性。

标签: perl


【解决方案1】:

通常避免使用全局变量的原因是您很容易遭受“污染” - 变量越多,被更多来源修改,就很难跟踪损坏的代码。

对于简短的脚本,您通常没问题。

不过,我真的会避免使用像 &fillnames; 这样的成语。那是在做一些你可能并不完全期望的事情。以这种方式调用 sub 会“通过”隐含变量,这不是一种好的风格(在我看来)。

改为:

foreach my $person ( @people ) {
   fillNames ( $person ); 
 }

子程序不能返回多个数组,你是对的。好吧,有点 - 它返回一个平面列表,并连接元素。如果要返回多个数组,则需要通过引用来完成。

例如:

sub return_two_arrays {

  my @array1 = ( "one", "two", "three" );
  my @array2 = ( "four", "five", "six" );
  return ( \@array1, \@array2 );
}

my ( $array1_ref, $array2_ref ) = return_two_arrays();
print join ( "\n", @$array1_ref );

不过,请注意 - 您的代码取消定义 @names,然后将一个值推入其中。这可能不是您想要做的——这正是使用“全局变量”可能导致的问题。因为事实上,您在@names 中只会有最后一个“名字”。

【讨论】:

  • 我现在可以看到最好避免使用全局变量。最初,我认为最好使用它们,因为它需要更少的整体代码行——我开始发现这并不总是最好的,但是
  • 更少的行并不总是意味着更好的代码,就像较短的帖子并不总是解释你的意思的最清晰的方式一样。与 perl 臭名昭著的那些压缩“单行”中的一个相比,拥有一页清晰明了的代码好。 perl 的真正优势在于它的灵活性——如果你没有使用它来编写漂亮而清晰的代码,那你就错了。
【解决方案2】:

这里没有简单明了的答案,但我想说这取决于脚本的大小和范围。

如果您的脚本足够小,可以很容易地跟踪全局变量,那么我会说这没问题。但是,一旦超过一定的大小和复杂程度,我就会对以这种方式使用全局数组持谨慎态度。

【讨论】:

  • 对于典型的初学者程序员,如果他们正在制作一个仅依赖于全局变量的子程序,那么代码可能不应该成为子程序,而只是内联代码。我想说你描述的大小和复杂性限制应该是 2 行,我们应该总是建议新程序员传递参数和返回值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 2022-07-22
  • 1970-01-01
  • 2011-05-18
  • 2014-11-22
  • 1970-01-01
相关资源
最近更新 更多