陈词滥调的答案是你必须使用local
,因为my *FH
它是一个语法错误。
“正确”(但不是很有启发性)的答案是你做错了。您应该使用词法文件句柄和三参数形式的open
代替。
sub newopen {
my $path = shift;
my $fh;
open($fh, '<', $path) or do {
warn "Can't read file '$path' [$!]\n";
return;
}
return $fh;
}
要真正回答为什么需要解释词法变量和全局变量之间以及变量范围和持续时间之间的区别。
变量的范围是程序中其名称有效的部分。范围是一个静态属性。另一方面,变量的持续时间是动态属性。持续时间是程序执行期间变量存在并保存值的时间。
my
声明一个词法变量。词法变量的范围从声明点到封闭块(或文件)的末尾。您可以在不同的范围内拥有其他具有相同名称的变量而不会发生冲突。(您也可以在重叠范围内重复使用名称,但不要这样做。)词法变量的持续时间是通过引用计数来管理的。只要至少有一个对变量的引用,该值就存在,即使该名称在特定范围内无效!my
还具有运行时效果——它分配一个具有给定名称的新变量。
local
有点不同。它对全局变量进行操作。全局变量具有全局范围(名称在任何地方都有效)和程序整个生命周期的持续时间。所做的是对全局变量的值local
进行临时更改。这有时被称为“动态范围”。更改从声明点开始,一直持续到封闭块的末尾,之后旧值被恢复。重要的是要注意新值不限于块——它在任何地方都是可见的(包括被调用的子例程)。引用计数规则仍然适用,因此您可以在更改过期后获取并保留对本地化值的引用。local
回到例子:*FH
是一个全局变量。更准确地说,它是一个“typeglob”——一组全局变量的容器。typeglob 包含每个基本变量类型(标量、数组、散列)以及其他一些内容的槽。从历史上看,Perl 使用 typeglobs 来存储文件句柄并将local
它们 - 化有助于确保它们不会相互干扰。词法变量没有类型团,这就是为什么说my *FH
是语法错误。
在现代版本的 Perl 中,词法变量可以而且应该用作文件句柄。这让我们回到了“正确”的答案。