揭秘 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 = 原始哈希 ------------------

perlmodperldata 上的其他文档。在引用成为 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 (*)的主要内容,如果未能解决你的问题,请参考以下文章

[css 揭秘]:CSS揭秘 技巧:多重边框

[css 揭秘] :CSS揭秘 技巧:条纹背景

[css 揭秘]:CSS揭秘 技巧:边框内圆角

安卓刷量技术揭秘

(转)写文章 以太坊(Ethereum)创世揭秘 以太坊(Ethereum)创世揭秘

算法揭秘Google Trips中存在了280年的古老算法揭秘