揭秘 Perl glob (*)
Posted
技术标签:
【中文标题】揭秘 Perl glob (*)【英文标题】:Demystifying the Perl glob (*) 【发布时间】:2011-06-19 10:09:48 【问题描述】:在this question,发帖人在一行中询问了如何执行以下操作:
sub my_sub
my $ref_array = shift;
my @array = @$ref_array;
根据我对基本 Perl 魔法的了解,我可以通过简单地使用类似的东西来避免:
sub my_sub
my $ref_array = shift;
for (@$ref_array)
#do somthing with $_ here
;
#use $ref_array->[$element] here
但是在this answer SO 的一位当地僧侣 tchrist 建议:
sub my_sub
local *array = shift();
#use @array here
当我问
在尝试学习中级 Perl 魔术,我能问一下,你是什么 在这里设置什么?你是 将@array 的引用设置为 传入的arrayref?如何 你知道你创建@array 和 不是 %array 或 $array?我可以在哪里 了解有关此 * 运算符的更多信息 (perlop?)。谢谢!
有人建议我将其作为新帖子提出,尽管他确实提供了很好的参考。无论如何,来了?有人可以解释什么被分配给什么以及如何创建@array而不是%array或$array?谢谢。
【问题讨论】:
您可能可以从this answer 中收集到一些关于 typeglob 的重要见解,这里还没有涉及到。 【参考方案1】:分配给全局
*glob = VALUE
包含一些依赖于VALUE
类型的魔法(例如,Scalar::Util::reftype(VALUE)
的返回值)。如果VALUE
是对标量、数组、散列或子例程的引用,则仅符号表中的该条目将被覆盖。
这个成语
local *array = shift();
#use @array here
当子例程的第一个参数是数组引用时,按文档说明工作。如果第一个参数是一个标量引用,那么只有$array
而不是@array
会受到赋值的影响。
一个小演示脚本,看看发生了什么:
no strict;
sub F
local *array = shift;
print "\@array = @array\n";
print "\$array = $array\n";
print "\%array = ",%array,"\n";
print "------------------\n";
$array = "original scalar";
%array = ("original" => "hash");
@array = ("orignal","array");
$foo = "foo";
@foo = ("foo","bar");
%foo = ("FOO" => "foo");
F ["new","array"]; # array reference
F \"new scalar"; # scalar reference
F "new" => "hash"; # hash reference
F *foo; # typeglob
F 'foo'; # not a reference, but name of assigned variable
F 'something else'; # not a reference
F (); # undef
输出:
@array = 新数组 $array = 原始标量 %array = 原始哈希 ------------------ @array = 原始数组 $array = 新标量 %array = 原始哈希 ------------------ @array = 原始数组 $array = 原始标量 %array = 新哈希 ------------------ @array = 富吧 $数组 = 富 %array = FOOfoo ------------------ @array = 富吧 $数组 = 富 %array = FOOfoo ------------------ @数组 = $数组= %数组= ------------------ @array = 原始数组 $array = 原始标量 %array = 原始哈希 ------------------perlmod
和 perldata
上的其他文档。在引用成为 Perl 的一部分之前的日子里,这个习惯用法有助于将数组和散列传递到子例程中。
【讨论】:
不要忘记当 RHS 到 typeglob 赋值恰好既不是 typeglob 也不是引用而是字符串时会发生什么。还要考虑当*
sigil 的操作数是字符串而不是裸字时会发生什么。最后,考虑local
。
正如这个答案所示,分配给 glob 会根据引用类型填充不同的插槽。您可以简洁地确保您具有正确的类型,如下所示:local *array = \@shift @_
。如果 ref 是一个数组,则引用/取消引用对 \@
是透明的,否则会抛出错误。
我仍在尝试阅读 tchrist 在问题评论中发布的链接中的一些内容,但是,这很好地回答了我的实际问题。谢谢!而且我认为我至少了解了要启动的符号表的一些基础知识!【参考方案2】:
以我公认的 Perl 知识不足为奇,我将冒险回答。 * 运算符分配符号表条目。据我了解,@array、%array 和 $array 都引用字符串“array”的相同符号表条目,但指向该条目中的不同字段:ARRAY、HASH 和 SCALAR 字段。因此,分配 local *array = shift;
实际上会将“数组”的整个本地符号表条目(包括 ARRAY、HASH 和 SCALAR 字段)分配给调用者中传递的内容。
【讨论】:
如果分配的东西是 glob 或 globref,是的;否则会更复杂。实际上,无论如何它更复杂,因为符号表条目就像一个保存“glob值”的“glob变量”,并且赋值设置的是值部分,而不是变量本身。以上是关于揭秘 Perl glob (*)的主要内容,如果未能解决你的问题,请参考以下文章