以我浅见,全局符号需要明确包名在Perl里是个常见的错误信息,而且具有相当的迷惑性。 至少对于初学者而言。

它可以简单的翻译为“你需要用my声明变量。”

最简单的例子

use strict;
use warnings;

$x = 42;

错误是

Global symbol "$x" requires explicit package name at ...

虽然实际的错误信息是准确的,但是对于Perl初学者来说并没什么用。 他们可能还不知道什么是包,更不用说怎么样才可以比$x更明确了。

这个错误是由于use strict引起的。

文档中的解释是: 如果你访问一个没有使用"our"或者"use vars"或者通过"my()"真正局部化声明的变量,会遇到一个编译期错误。

初学者很可能每个脚本都会以use strict开头,也很可能早就学过了my

我不知道perl是否会更改错误信息。这不是本文要讨论的。本文只是帮初学者以他们自己的语言理解这个错误信息是什么意思。

要消除这个错误,需要这么写:

use strict;
use warnings;

my $x = 42;

亦即,需要在第一次使用变量之前,用my声明变量

糟糕的办法

另一个“办法”是删除strict: The other "solution" is to remove strict:

#use strict;
use warnings;

$x = 23;

这样可以运行,但是这个代码会产生一个警告Name "main::x" used only once: possible typo at ...

不管怎样,通常你都不会不系安全带开车吧?

例子2: 作用域

新手常犯的错误还有下面这样的:

use strict;
use warnings;

my $x = 1;

if ($x) {
my $y = 2;
}

print $y;

错误信息跟上边的一样:

Global symbol "$y" requires explicit package name at ...

这令很多人迷惑不解。尤其是他们已经开始编程的,毕竟他们使用my声明了$y

首先,这有个小的视觉问题。my $y = 2;的缩进没有了。 要是能像下一个例子这样向右缩进一些空格或者一个tab键,问题的根源就一目了然了:

use strict;
use warnings;

my $x = 1;

if ($x) {
    my $y = 2;
}

print $y;

问题在于变量$y是在块里声明的(一对大括号),在代码块之外就不可见了。 这就是变量的作用域

作用域的概念在不同的编程语言里是不一样的。 在Perl里,大括号包含的块创建了一个作用域。 它里边使用my声明的东西,在块之外是访问不到的。

(另外,$x = 1的存在只是让创建作用域的语句看起来更真实。)

解决方案是或者在块内调用print

use strict;
use warnings;

my $x = 1;

if ($x) {
    my $y = 2;
    print $y;
}

或者在块外部定义变量(而非内部!!):

use strict;
use warnings;

my $x = 1;
my $y;

if ($x) {
    $y = 2;
}

print $y;

用哪一种取决于实际的情况。这些只是从语法上可能的正确解决方案。

当然,如果你忘了删除块内的my,或者if $x判断为假,那我们会碰到一个使用了未初始化值的警告。

其他办法

另有章节专门讲解ouruse vars的作用,或者如何完全限定变量名称。