为什么没有文件句柄的专用类型?



哈希值和标量在不同的命名空间中。我可以这样写:

%foo = %bar

而不用担心弄乱%bar的值。

为什么相同的逻辑不适用于文件句柄?如果我这样做:

*FOO = *BAR

我不仅使<FOO>做与<BAR>相同的事情,我还改变了$FOO, @FOO%FOO

这样做仅仅是因为Perl最初是这样编写的,并且它是根深蒂固的吗?因为没有更多的非字母数字前缀字符了?或者它这样工作是有原因的吗?

为什么相同的逻辑不适用于文件句柄?

首先*BAR不是一个文件句柄;它是一个球体。"Glob"是"type Glob"或"typeglob"的缩写。Globs是组成符号表的元素。

正如您所述,*FOO = *BAR;复制glob,就像%foo = %bar;复制哈希一样。所以同样的逻辑也适用于文件句柄 globs。

在Perl中没有办法具体地引用文件句柄。它总是通过glob、引用或对glob的引用间接完成的。

如果您想将文件句柄从一个glob复制到另一个glob,您可以使用以下命令:

 *FOO = *BAR{IO};

一个glob(例如*FOO)是一个类似哈希的关联数组,具有固定的一组键,包括SCALAR, ARRAY,…和IO。将引用赋给glob(例如*BAR{IO}返回的glob)将自动将引用赋给glob的适当槽位。

但是你为什么要摆弄globs呢?

*foo = $bar;

*foo = *bar{SCALAR};

复制字符串?不,为什么要复制一个文件句柄。和字符串一样,你应该使用

 $foo = $bar;

你遇到困难的根本原因是因为你使用的是13年前(6个主要版本)过时的技术。你不应该使用全局变量;您应该使用具有适当作用域的词汇。

 open(my $BAR, ...) or die $!;
 my $FOO = $BAR;

 my $FOO = *STDOUT;

然后像使用FOO一样使用$FOO

while (<FOO>)    =>   while (<$FOO>)
print FOO ...;   =>   print $FOO ...;
func(*FOO);     =>   func($FOO);

你可以这样做:

*FOO = *BAR{IO}

但是,老实说,最好不要使用裸字文件句柄(看起来像FOO)。它是历史遗留的产物,在Perl 5.6中被淘汰了(很多年前)。相反,你应该把文件句柄放在标量中:

open my $foo, '<', 'filename';
my $line = <$foo>;
# ⋮

然后,当然,你可以像复制任何其他标量$bar = $foo一样复制它们。

另外,通常要避免使用两个名称相同的变量,因为这会引起混淆。

my @a = (1, 2, 3);
my $a = 4;
my %a = (5 => 6, 7 => 8);
say $a, $a[0], $a{5}; # the scalar, the array, the hash (in that order)
say @a{5,7};          # the hash

查看Perldata下的文档(参见Typeglobs和Filehandles一节)。第一部分是:

Perl使用了一个叫做typeglob的内部类型来保存整个符号表项。typeglob的类型前缀是*,因为它表示所有类型。这曾经是通过引用将数组和哈希值传递给函数的首选方式,但现在我们有了真正的引用,很少需要这样做了。 肯

最新更新