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

Posted

技术标签:

【中文标题】Perl 词法范围变量在声明中的效率【英文标题】:Perl lexically scoped variables effiency in declaration 【发布时间】:2014-06-07 00:35:19 【问题描述】:

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

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

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

有相当多的变量,在程序顶部进行初始变量声明似乎是重复的,以便以后可用于输出/报告目的(并保持符合严格的编译指示)。根据我的理解和迄今为止收到的所有 cmets,这似乎是唯一的方法,因为根据定义,词法范围的变量仅在其声明的范围内持续存在。因此,为了使其成为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"; 

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

根据已收到的反馈,由于定义的范围限制,答案似乎是明确的“否”。

【问题讨论】:

你有什么问题? 是的@secJ,将变量限制在尽可能小的范围内是更好的编码风格。您有时会看到您所描述的 C 程序员的风格来到 perl。此外,应该始终给出自记录代码的变量名称。 $var 什么也没交流。但是,听起来您没有可以直接回答的问题,因此您应该重新构建,或者我们应该将其关闭,因为它太宽泛了。 嗯,完全不用担心变量声明的效率 @Miller 我试图进一步澄清我的问题。我想知道如何使作用域变量可以在它们被设置的循环之外访问。所以使用 foreach 循环进行计算等,但稍后可以在报告输出中调用最终值(在该 foreach 循环之外) . 您的新问题的答案是“否”;您必须在将要使用它们的范围内声明变量,而不是在某个内部范围内。 【参考方案1】:

根据您自己的问题:

所以问题是:是否有一个可接受的快捷方式在上面的 foreach 循环中声明 $var1 并将其范围升级到 foreach 循环之外,所以它实际上是“全局”的?这将避免需要在程序顶部将其声明和初始化为 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 格式。

但是,很清楚:您不需要“将变量声明并初始化为 undef”。如果你这样做:

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

这些变量已经初始化为undef

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

【讨论】:

感谢您的回复。 @ikegami 提到了使用默认的package,但我不知道如何在 Perl 中访问/设置这些变量,所以直到现在我都不确定这是正确的方法。这正是我想要达到的。感谢您的详细说明和解释。【参考方案2】:

我只是想知道是否有一种捷径可以将变量的范围提升为全局变量,而不管它在哪里声明,并且仍然保持在严格的参数范围内?

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

use vars qw( $foo );

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

【讨论】:

你之前提到的默认package 是我想问的。感谢您的努力和帮助。

以上是关于Perl 词法范围变量在声明中的效率的主要内容,如果未能解决你的问题,请参考以下文章

perl6 subs 真的是词法范围还是有额外的?

闭包.词法作用域#

Javascript词汇范围

Perl 变量范围问题

当前范围错误中的重复声明;两个循环具有相同的变量,可变范围

什么是 C++ 中的“变量‘i’未在范围内声明”?