散列和标量位于不同的命名空间中。所以我可以这样做:
%foo = %bar
不用担心会弄乱%bar
.
为什么相同的逻辑不适用于文件句柄?如果我这样做:
*FOO = *BAR
我不仅<FOO>
做了与 相同的事情<BAR>
,我还改变了$FOO
, @FOO
,%FOO
以及。
是不是因为 Perl 最初是这样写的,而且它根深蒂固?因为没有更多的非字母数字前缀字符了?还是有理由必须以这种方式工作?
散列和标量位于不同的命名空间中。所以我可以这样做:
%foo = %bar
不用担心会弄乱%bar
.
为什么相同的逻辑不适用于文件句柄?如果我这样做:
*FOO = *BAR
我不仅<FOO>
做了与 相同的事情<BAR>
,我还改变了$FOO
, @FOO
,%FOO
以及。
是不是因为 Perl 最初是这样写的,而且它根深蒂固?因为没有更多的非字母数字前缀字符了?还是有理由必须以这种方式工作?
为什么相同的逻辑不适用于文件句柄?
首先*BAR
不是文件句柄;这是一个球。“glob”是“type glob”或“typeglob”的缩写。Glob 是符号表的组成部分。
正如您所说,*FOO = *BAR;
复制 glob 就像%foo = %bar;
复制哈希一样。所以同样的逻辑也适用于文件句柄glob。
在 Perl 中没有办法专门引用文件句柄。它总是通过 glob、引用或对 glob 的引用间接完成。
如果要将文件句柄从一个 glob 复制到另一个 glob,可以使用以下命令:
*FOO = *BAR{IO};
glob(例如*FOO
)是一个类似于哈希的关联数组,具有一组固定的键,包括SCALAR
, ARRAY
, ... 和IO
。分配对 glob 的引用(例如由 返回*BAR{IO}
的引用)将自动将该引用分配给 glob 的正确插槽。
但是你为什么要搞乱球?你会怎么做
*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>;
# ⋮
然后,当然,您可以像复制任何其他 scalar 一样复制它们$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 的类型前缀是 *,因为它代表所有类型。这曾经是通过引用将数组和散列传递给函数的首选方式,但现在我们有真正的引用,这很少需要。
肯