Perl词法规范变量在声明中的效率

时间:2014-06-07 00:35:19

标签: perl variables scope

最终修改:为了清楚起见,我正在对此问题进行最后一次编辑。我相信它已在所有评论中得到了回答,但如果有这样的选择,我认为最好为未来的读者清理问题。

我最近继承了某人的Perl代码,这是一个有趣的设置,我想知道它是否可以提高效率。

该程序设置为使用strictwarnings(应该如此)。该程序设置为使用global个变量;意味着变量在程序顶部声明并初始化为undef。然后,在程序内的各个循环中,将超出初始undef的特定值分配给变量。设置完成后,会有一个单独的报表部分(在所有内部循环和子例程运行之后)使用变量作为其内容。

有很多变量,只是在程序的顶部创建一个初始变量声明似乎是重复的,以便稍后可用于输出/报告目的(并保持符合严格的编译指示)。根据我的理解和迄今为止收到的所有评论,似乎这是唯一的方法,因为定义的词汇范围变量仅在其声明的范围内持续存在。因此,为了使它global,它需要提前声明(即在顶部)。

我只是想知道是否有一条快捷方式可以将变量的范围提升为全局,而不管它在何处声明,当然仍然保持在strict's个参数范围内?

我之前的例子令人困惑,所以我在这里写一个伪代码示例来传达这个概念(我没有原始资料来源):

# Initial declaration to create "Global variables" -- imagine about 30 or so
my ($var1, $var2, $var3); # Global

# Imagine a foreach loop going through a hash and assigning values 
# to previously declared variables
for my $k (keys %h){
  ...
  $var = 1; #$var gets set to 1 within the foreach loop
  ...
}
print "The final calculated report is as follows:\n";

#output $var after loop is done later in program
print "Variable 1 comes to $var1\n"; 

所以问题是:是否有一个可接受的快捷方式在$var1循环中声明foreach并将其范围升级到foreach循环之外,因此它实际上是#34;全球&#34 ;?这样就可以避免在程序顶部声明并初始化为undef,并且仍然可以在程序的输出中使用它。

根据已经收到的反馈意见,答案似乎是一个强调"否"由于定义的范围限制。

2 个答案:

答案 0 :(得分:2)

根据您自己的问题:

  

所以问题是:是否有一个可接受的快捷方式,在上面的foreach循环中声明$ var1并将其范围升级到foreach循环之外,因此它实际上是" Global"?这样就可以避免在程序顶部声明并初始化为undef,并且仍然可以在程序的输出中使用它。

您可以通过使用包括命名空间的整个名称来引用变量名而不首先声明它:

use strict;
use warnings;

my %h = (
    first   => 'value 1',
    second  => 'value 2',
    third   => 'value 3',
);

for my $k (keys %h) {
    print "Processing key $k...\n";
    $main::var = 1;
}

print "Variable var is now $main::var\n";

我假设main为您的命名空间,这是默认设置。如果您的脚本声明了package,那么您需要使用该名称。另外,如果您没有先声明变量,则每次都需要使用整个package :: name格式。

然而,事实很明确:您不需要声明并初始化变量以取消定义"。如果你这样做:

my ($var1, $var2, $var3);

这些变量已初始化为undef

现在,您还需要了解词法变量和全局变量之间的区别。使用关键字my在脚本顶部声明变量将使其在脚本的所有其余部分中可用,无论您是在块内还是在块外。但它们并非真正全球化,因为任何外部模块或脚本都看不到它们。如果您将关键字my更改为our,则它们是全局的,并且可以在该脚本之外的任何位置显示。

答案 1 :(得分:1)

  

我只是想知道是否有一个快捷方式可以将变量的范围提升为全局,而不管它在何处被声明,并且当然仍然保持在严格的参数范围内?

使用全局变量是愚蠢的,但可能。

use vars qw( $foo );

在任何使用之前它仍然需要存在。