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