哈希值和标量在不同的命名空间中。我可以这样写:
%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的类型前缀是*,因为它表示所有类型。这曾经是通过引用将数组和哈希值传递给函数的首选方式,但现在我们有了真正的引用,很少需要这样做了。 肯