我正在审核this question,特别是来自埃里克斯特罗姆先生的response,并且对于一部分更神奇的"内在的元素。请查看上下文链接的问题,因为我只想了解此块的内部部分:
for (qw($SCALAR @ARRAY %HASH)) {
my ($sigil, $type) = /(.)(.+)/;
if (my $ref = *$glob{$type}) {
$vars{$sigil.$name} = /\$/ ? $$ref : $ref
}
}
因此,它会循环显示三个单词,将每个单词分成两个变量,$sigil
和$type
。 if {}
块是我不理解的。我怀疑( .. )
中的部分是$glob{$type}
内的内容的象征性引用...必须有一些"魔法" (我不理解的潜在机制的一些深奥元素)依靠那里来确定"指向"的类型。数据?
下一行也部分令人费解。在我看来,我们正在分配vars哈希,但rhs在做什么?我们没有在最后一次操作中分配$_
($ref
已分配),那么在/\$/
块中进行比较的是什么?我的猜测是,如果我们处理标量(虽然我无法辨别出它们是什么),我们将$ref
var deref并将其直接存储在散列中,否则,我们存储引用。
所以,只是想看看这三行中发生了什么的故事。非常感谢!
答案 0 :(得分:5)
你已经找到了Perl语言中最神秘的部分之一,我可以通过Symbol Tables and Typeglobs来自brian d foy的优秀掌握Perl 来引用你最好的解释。另请注意,页面底部还提供了Perl自己文档的相关部分,其中最相关的部分是perldata
中的Typeglobs and Filehandles。
基本上,perl符号表的工作方式是每个包都有一个“stash” - 一个“符号表哈希” - 其名称与包装但带有一对拖尾分号。因此,默认包main
的存储称为%main::
。如果你运行这个简单的程序
perl -E"say for keys %main::"
您将看到所有熟悉的内置标识符。
存储元素的值是对 typeglobs 的引用,它们也是哈希值,但具有与不同数据类型对应的键SCALAR
,{ {1}},ARRAY
,HASH
等以及对具有该类型和标识符的数据项的引用值。
假设您定义了一个标量变量CODE
,或者更全面地定义了$xx
$main:xx
现在our $xx = 99;
包的存储为main
,%main::
引用了标识为xx
的所有数据项的typeglob所以,因为typeglobs的 sigil 是星号$main::{xx}
,就像标量标识符有一个美元*
一样,我们可以将其取消引用为$
。要获取对标识为*{$main::{xx}}
的标量变量的引用,可以使用xx
字符串对此类型地址进行索引,并提供SCALAR
。再一次,这是我们所追求的变量的引用,所以要收集它的值,它需要再次引用,如果你写了
*{$main::{xx}}{SCALAR}
然后您会看到say ${*{$main::{xx}}{SCALAR}};
。
当用单个语句写出来时,这可能看起来有点复杂,但在拆分时它是相当复杂的。您的问题中的代码将变量99
设置为对typeglob的引用,对应于$glob
$main::xx
现在,如果我们my $type = 'SCALAR';
my $glob = $main::{xx};
my $ref = *$glob{$type};
获得say $ref
或类似内容,这是SCALAR(0x1d12d94)
之前的引用,则打印$main::xx
将按预期显示$$ref
随后对99
的赋值是直截了当的Perl,我认为一旦你得到一个包符号表是一个典型的东西,或者实际上只是一个哈希的原则,你就不会有任何问题。哈希。
答案 1 :(得分:4)
迭代的元素是 strings 。由于我们在循环顶部没有词法变量,因此元素变量为$_
。它在整个循环中保留了这个价值。这些字符串中只有一个具有文字美元符号,因此我们告诉'$SCALAR'
与其他案例之间的区别。
所以它正在做的是从包级typeglob中获得3个插槽(有时缩短,小歧义为“glob”)。 *g{SCALAR}
,*g{ARRAY}
和*g{HASH}
。 glob存储散列和数组作为引用,因此我们只是将引用存储到散列中。但是,glob将标量存储为标量的引用,因此需要取消引用,才能存储为标量。
所以如果你有一个glob *a
并且在你的包中你有:
our $a = 'boo';
our @a = ( 1, 2, 3 );
our %a = ( One => 1, Two => 2 );
产生的哈希值为:
{ '$a' => 'boo'
, '%a' => { One => 1, Two => 2 }
, '@a' => [ 1, 2, 3 ]
};
同时可以认为glob看起来像这样:
a =>
{ SCALAR => \'boo'
, ARRAY => [ 1, 2, 3 ]
, HASH => { One => 1, Two => 2 }
, CODE => undef
, IO => undef
, GLOB => undef
};
所以要专门回答你的问题。
if (my $ref = *$glob{$type}) {
$vars{$sigil.$name} = /\$/ ? $$ref : $ref
}
如果没有使用插槽,则它是undef。因此,为$ref
分配了引用或undef
,其评估为true
作为参考,false
评估为undef
。所以 if 我们有一个引用,然后将该glob时隙的值存储到哈希中,将参考存储在哈希中,如果它是一个“容器类型”,但如果它是一个“容器类型”则取值标量。并且它与$sigil . $name
哈希中的密钥%vars
一起存储。