我正在审查这个问题,特别是埃里克斯特罗姆先生的回应,并对其中一部分更"神奇"的元素提出了疑问.请查看上下文的链接问题,因为我只是想了解这个块的内部部分:
for (qw($SCALAR @ARRAY %HASH)) {
my ($sigil, $type) = /(.)(.+)/;
if (my $ref = *$glob{$type}) {
$vars{$sigil.$name} = /\$/ ? $$ref : $ref
}
}
Run Code Online (Sandbox Code Playgroud)
因此,它循环超过三个单词,将每个单词分成两个变量,$sigil并且$type.该if {}块是什么我不理解.我怀疑其中的部分( .. )正在获得对内容中的内容的符号引用$glob{$type}...必须有一些"魔法"(我尚未理解的潜在机制的一些深奥元素)依赖于那里来确定其类型"尖头"数据?
下一行也部分令人费解.在我看来,我们正在分配vars哈希,但rhs在做什么?我们没有$_在最后一次操作$ref中分配(已分配),那么在/\$/块中进行比较的是什么?我的猜测是,如果我们正在处理标量(虽然我无法辨别出它们是什么),我们deref $refvar并将其直接存储在散列中,否则,我们存储引用.
所以,只是想看看这三行中发生了什么的故事.非常感谢!
迭代的元素是字符串。由于循环顶部没有词法变量,元素变量是$_。它在整个循环中保留该值。这些字符串中只有一个具有字面意义的美元符号,因此我们要区分'$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 );
Run Code Online (Sandbox Code Playgroud)
结果散列将是:
{ '$a' => 'boo'
, '%a' => { One => 1, Two => 2 }
, '@a' => [ 1, 2, 3 ]
};
Run Code Online (Sandbox Code Playgroud)
同时,glob 可以被认为是这样的:
a =>
{ SCALAR => \'boo'
, ARRAY => [ 1, 2, 3 ]
, HASH => { One => 1, Two => 2 }
, CODE => undef
, IO => undef
, GLOB => undef
};
Run Code Online (Sandbox Code Playgroud)
所以特地回答你的问题。
if (my $ref = *$glob{$type}) {
$vars{$sigil.$name} = /\$/ ? $$ref : $ref
}
Run Code Online (Sandbox Code Playgroud)
如果一个插槽没有被使用,它就是 undef。因此$ref将被分配一个或参考undef,其计算结果为true作为参考和false作为undef。因此,如果我们有一个引用,则将该 glob 插槽的值存储到哈希中,如果它是“容器类型”,则获取存储在哈希中的引用,但如果它是标量,则获取该值。它与哈希中的键$sigil . $name一起存储%vars。
你已经找到了Perl语言中最神秘的部分之一,我可以通过引用brian d foy优秀的Mastering Perl中的符号表和Typeglobs来解释.还需要注意的是有页面,最相关的,其中是底部的Perl的自己的文档中的有关章节进一步引用类型团和文件句柄在.perldata
从本质上讲,perl符号表的工作方式是每个包都有一个"存储" - 一个"符号表哈希" - 其名称与包相同,但带有一对尾随分号.因此main调用默认包的存储%main::.如果你运行这个简单的程序
perl -E"say for keys %main::"
Run Code Online (Sandbox Code Playgroud)
您将看到所有熟悉的内置标识符.
该值用于藏匿元素要引用类型团,而这又是散列但具有对应于不同的数据类型的密钥,SCALAR,ARRAY,HASH,CODE等,以及那些对与该类型和标识符的数据项的引用值.
假设你定义一个标量变量$xx,或者更完整,$main:xx
our $xx = 99;
Run Code Online (Sandbox Code Playgroud)
现在藏匿的main包%main::,并与该标识符的所有数据项的类型团xx被引用$main::{xx}的话,因为印记的类型团是一个明星*在相同的方式,标标识符有一块钱$,我们可以反引用本作*{$main::{xx}}.要获取对具有标识符的标量变量的引用xx,可以使用SCALAR字符串赋值来索引此typeglob *{$main::{xx}}{SCALAR}.再一次,这是对我们所追求的变量的引用,所以要收集它的值,它需要再次解除引用,如果你写的话
say ${*{$main::{xx}}{SCALAR}};
Run Code Online (Sandbox Code Playgroud)
然后你会看到99.
当用单个语句编写时,这可能看起来有点复杂,但在拆分时它是相当复杂的.您的问题中的代码将变量$glob设置为对typeglob的引用,对应于此类型$main::xx
my $type = 'SCALAR';
my $glob = $main::{xx};
my $ref = *$glob{$type};
Run Code Online (Sandbox Code Playgroud)
现在,如果我们say $ref得到SCALAR(0x1d12d94)或类似,这是$main::xx以前的参考,打印$$ref将按99预期显示.
随后的赋值@vars是直截了当的Perl,我认为你不应该理解一旦你得到包符号表是一个典型的东西,或者实际上只是一个散列哈希的原则.
| 归档时间: |
|
| 查看次数: |
101 次 |
| 最近记录: |