- 论坛徽章:
- 0
|
本帖最后由 黑色阳光_cu 于 2010-12-31 12:18 编辑
Perl 的文件句柄本质上是保存在 typeglob 里的,当你调用 open 时,有一些奇妙的事发生了:- open(FH, "<", "urfile.txt");
- warn *FH{IO};
复制代码 可以看到,FH 的文件句柄保存在 *FH 里,具体的是保存在 *FH{IO} 里。FH 是一个裸词,在 open 调用里,Perl 会把裸词转为对应的 typeglob,相当于- open(*FH, "<", "urfile.txt");
复制代码 所以,当要传递句柄时,要把裸词形式的句柄转成对应的 typeglob 或者 typeglob 的引用:- sub func
- {
- my $fp = $_[0];
- while (<$fp>)
- {
- print;
- }
- }
- open(FH, "<", "urfile.txt");
- func(\*FH);
复制代码 这样子相当不方便,后来,Perl 允许这样子的语法:- open(my $fp, "<", "urfile.txt");
- warn $fp;
- while (<$fp>)
- {
- print;
- }
复制代码 可以看到 $fp 就是一个 typeglob 的引用。打印 *{$fp} 时显示 *main::$fp , 但下面这个代码表明,直接用当前的 *main::$fp 却不行:- open(my $fp, "<", "urfile.txt");
- warn *{$fp};
- while (<*{'main::$fp'}>)
- {
- print;
- }
复制代码 再则,当 $fp 超过作用域时,文件会自动被关闭, $fp 这个句柄是词法作用域的。 看来 $fp 不简单的等同于 \*{'main::$fp'} ,那又是怎么做到的?
因为,typeglob 是一个全局的资源,为了取得词法域的效果,可以借助于 local 。open($fp, "<", "urfile.txt") 大概等同于这个写法:- my $fp;
- {
- local *{'main::$fp'};
- open(*{'main::$fp'}, "<", "urfile.txt");
- my $tmp = *{'main::$fp'};
- $fp = \$tmp;
- }
- warn $fp;
- while (<$fp>)
- {
- print;
- }
复制代码 注意那个 $tmp ,当 my $tmp = *{'main::$fp'} 后,$tmp 和 *{'main::$fp'} 指向同一个 typeglob 值。当超过作用域后,*{'main::$fp'} 恢复原值,则 $fp 是 $tmp 的唯一引用。所以,超过作用域后,$fp 就不简单的等同于当前的 \*{'main::$fp'} ,而当 唯一引用 $fp 也超过作用域时,文件就被自动关闭了。借助于 local ,Perl 提供了词法作用域的文件句柄。在这里,也可以看出 Perl 解决问题的智慧。 |
|