全局符号需要明确包名
以我浅见,全局符号需要明确包名在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判断为假,那我们会碰到一个使用了未初始化值的警告。
其他办法
另有章节专门讲解our、use vars的作用,或者如何完全限定变量名称。

Published on 2013-05-02