2014-10-09 29 views
2

我在回顾Eric Strom先生的this question,尤其是response,并对其中更“神奇”的部分提出了疑问。请查看上下文链接的问题,因为我只是想了解这个块的内侧部分:需要帮助理解脚本的部分(球体和参考文献)

for (qw($SCALAR @ARRAY %HASH)) { 
    my ($sigil, $type) = /(.)(.+)/; 
    if (my $ref = *$glob{$type}) { 
     $vars{$sigil.$name} = /\$/ ? $$ref : $ref 
    } 
} 

因此,它遍历三个字,打破各分为两个瓦尔,$sigil$typeif {}块是我不了解的。我怀疑(..)内的部分获得了$glob{$type}内的符号引用......必须有一些“魔术”(我还不了解的底层机制的某些深奥元素)依赖于那里来确定类型的“指向”数据?

下一行也是部分令人困惑。在我看来,我们正在分配到变量哈希,但是什么是rhs在做什么?我们在最后一次操作中没有分配到$_(分配了$ref),那么与/\$/区块中的比较是什么?我的猜测是,如果我们正在处理一个标量(虽然我没有看清楚我们是怎么做的),但是我们去掉这个var并将其直接存储在散列中,否则我们就存储这个引用。

所以,只需要寻找这三行中发生的事情的一个小故事。非常感谢!

回答

4

迭代的元素是字符串。由于我们在循环的顶部没有词汇变量,因此元素变量为$_。它在整个循环过程中保留了这个值。这些字符串中只有一个字符串具有字面美元符号,所以我们告诉'$SCALAR'和其他情况之间的差异。

所以它正在从包级别获得3个槽位(有时候缩短了,而且的小小的含糊不清到“glob”)。 *g{SCALAR}*g{ARRAY}*g{HASH}。 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 ] 
}; 

同时,水珠可以被认为是这个样子:

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。所以,如果我们有一个参考,那水珠槽的值存储到哈希值,以存储在哈希参考,如果它是一个“容器类型”,但走的是价值,如果它是一个标量。并且它与中的密钥一起存储在%vars哈希中。

+0

哦......我明白了。明确perl欺骗正在进行,但这是有点整洁!最后一点混淆......在原始链接答案中,变量'$ glob'存储'* main :: eval_code'的值(例如,从测试脚本的输出中复制;注意前导的'*') 。当'* $ glob {SCALAR}'被评估时,是评估(在伪代码中)'*(* main :: eval_code){SCALAR}'? * *如何解决? – Jon 2014-10-09 16:53:25

+1

关于使用'$ a'来达到自己的目的通常的惩罚! – Borodin 2014-10-09 17:00:23

+0

@Jon,您知道签名'''','@'和'%',也许您知道'&call_this_sub('a')'中的遗留CODE签名',井符号有一个印记也是。最不为人知的是'*',它告诉perl将其解决到系统表。 “符号”和typeglob几乎是一回事。 – Axeman 2014-10-10 17:58:51

5

你在Perl语言的最晦涩的部分之一击中,我可以从brian d foy的优秀掌握的Perl指你Symbol Tables and Typeglobs最好的解释。还需要注意的是有在页面的底部,其中最相关的是perldataTypeglobs and Filehandles Perl的自己的文档中的相关章节进一步引用。

从本质上讲,Perl的方式符号表的工作是每一个“藏匿” - “符号表散列” - 他的名字是一样的包,但有一对尾随分号。所以默认包main的存储称为%main::。如果你运行这个简单的程序

perl -E"say for keys %main::" 

你会看到所有熟悉的内置标识符。

为藏匿要素是类型团,这再次是散列,但具有对应于不同数据类型的密钥,SCALARARRAYHASHCODE等,并且对于所述的参考值的参考具有该类型和标识符的数据项目。

假设你定义一个标量变量$xx,或更充分,$main:xx

our $xx = 99; 

现在藏匿main%main::,并与该标识符xx所有数据项的类型团被引用$main::{xx}所以,因为typeglobs的印记是一个星标*,与标量标识符有一个美元$相同,我们可以将其解引用为*{$main::{xx}}。要获得引用具有标识xx变量,该类型团可以与SCALAR字符串进行索引,从而*{$main::{xx}}{SCALAR}。再次,这是一个参考到我们以后是变量,所以要收集它的价值了,需要再一次提领,如果你写

say ${*{$main::{xx}}{SCALAR}}; 

然后你会看到99

写在一个语句的时候,却是相当stratighforward当分手这可能看起来有点复杂。在你的问题中的代码具有可变$glob设置为一个类型团的引用,如果我们say $ref我们得到SCALAR(0x1d12d94)或类似的对应于这相对于$main::xx

my $type = 'SCALAR'; 
my $glob = $main::{xx}; 
my $ref = *$glob{$type}; 

现在,这是$main::xx的引用作为前,并且打印$$ref将按预期显示99

后续分配给@vars是简单的Perl,我不认为你应该有任何理解,即一旦你得到包符号表是一堆typglobs,或者只是散列哈希的原则。

+0

And ...当我将'$ main :: {name}'分配给某个东西时,我得到了指向存储条目(对于'name')的“指针”,这将是该符号的glob插槽。直到我输出'$ main :: {name}'和'$ main :: name'时,我为什么要得到前导'''sigil'有点困惑。 – Jon 2014-10-09 18:20:28

+0

鲍罗丁,感谢您在perl的glob内部快速课程。你是对的,这是一门非常神秘的语言领域,但很明显,有时候非常有用。我接受另一个人的回答作为“问题的答案”,但不要将其解释为意味着我更重视你的回答!我用这两个答案来获得所需的理解。谢谢! – Jon 2014-10-10 16:07:34