Perl 数组推送和引用

Perl 数组推送和引用,perl,Perl,我是一名perl初学者,我遇到了一段代码,如下所示: my @Numbers=(); push(@{$Numbers[0]},3,8,9); push(@{$Numbers[1]},5); print join(",",@{$Numbers[0]}); print "\n"; print join(",",@{$Numbers[1]}); print "\n"; 我很难理解推送到{$Numbers[0]}和

我是一名perl初学者,我遇到了一段代码,如下所示:

my @Numbers=();

push(@{$Numbers[0]},3,8,9);
push(@{$Numbers[1]},5);

print join(",",@{$Numbers[0]});
print "\n";

print join(",",@{$Numbers[1]});
print "\n";

我很难理解推送到{$Numbers[0]}{$Numbers[1]}上的操作是什么。推送是否会自动创建对数字数组中[3,8,9]和[5]的数组引用?我不难理解下面的语法,我认为这是更常见的语法,但我没有遇到我在上面粘贴的语法,我猜它也使用自动生动化来填充带有引用的数字数组

my @Numbers=();

push(@Numbers,[3,8,9]);
push(@Numbers,[5]);

print join(",",@{$Numbers[0]});
print "\n";

print join(",",@{$Numbers[1]});
print "\n";

使用Data::Dumper查看发生了什么

#! /usr/bin/perl

use Data::Dumper;

my @Numbers=();

push(@Numbers,[3,8,9]);
push(@Numbers,[5]);

print Dumper(@Numbers);
输出:

$VAR1 = [
          3,
          8,
          9
        ];
$VAR2 = [
          5
        ];
如果将数组传递给转储程序,则元素将被解释为多个参数

圆括号是数组,矩形括号是数组引用<代码>推送仅对数组有效,但对数组引用无效。有关引用和反引用的详细信息,请参阅Perl手册

可以使用反斜杠将数组转换为数组引用:

print Dumper(\@Numbers);
现在,Dumper用矩形括号显示引用

$VAR1 = [
          [
            3,
            8,
            9
          ],
          [
            5
          ]
        ];
您也可以将数字作为引用,但在将其传递给push之前,必须先取消引用

#! /usr/bin/perl

use Data::Dumper;

my $Numbers=[];

push(@$Numbers,[3,8,9]);
push(@$Numbers,[5]);

print Dumper($Numbers);
现在你会明白这一点:

push(@{$Numbers[0]},3,8,9);
  • $Numbers[0]
    获取数组的第一个元素(标量)
  • @{$Numbers[0]}
    将标量反引用到数组中
  • push
    将三个标量
    3
    8
    9
    追加到取消引用的数组中

这将导致创建一个数组引用。

有两个功能在发挥作用,其中一个确实是


我马上就要进行自我激活了。首先,让我们考虑当我们访问<代码> $编号[0 ] < /代码>时,<代码> @编号<代码>是空的。这不是问题。Perl将自动扩展数组以包含此元素。[1]

my@a;
$a[3]=123;#好啊
打印(转储程序(\@a));\[未定义,未定义,未定义,123]
这并不是文档中所说的“自生”,但它非常相似,有些人也会称之为“自生”


正如我提到的,第二个特征确实是自生。Autovification是通过取消引用自动创建匿名变量。具体来说,它发生在取消引用未定义的标量时。[2]

在这种情况下,Autovification会创建一个数组,因为
@BLOCK
是一个数组解引用。对该数组的引用将创建并存储在以前的未定义标量中

换言之,自生使得

push@{$ref},列表;
实际上相当于

push@{$ref/=[]},列表;

if(!defined($ref)){
我的@anon;
$ref=\@anon;
}
推送@$ref,列表;

这可能只是这个问题的一个人为的例子,但请注意,发布的代码很奇怪。我们知道
$Numbers[0]
$Numbers[1]
是未定义的,所以我们不需要
推送

my@nums;
@{$nums[0]}=(3,8,9);#还有自生。
@{$nums[1]}=5;
既然我们知道,
$Numbers[0]
$Numbers[1]
是未定义的,我们也就没有必要依赖于自动生命化

my@nums;
$nums[0]=[3,8,9];
$nums[1]=[5];
让我们去掉那些硬编码的索引

my@nums;
按@nums[3,8,9];
推送@nums,[5];
以及最后的简化

my@nums=(
[ 3, 8, 9 ],
[ 5 ],
);

  • 这仅在左值上下文中发生,也就是说,当引用的变量预期会被修改/修改时<代码>说$a[@a]不会扩展数组,即使它在最后一个元素之后访问一个元素

  • 它还必须处于左值上下文中<代码>我的@copy=@{$unde}将不会自动激活


  • 打印数组或散列转储程序以了解结构。请参阅。@vkk05使用Data::Dumper打印数组。看起来第一个和第二个示例完全相同。两者都在数字数组中创建两个引用。只是第一个例子和语法并不常见——至少我在任何地方都没有见过。如果你像使用排序字典一样使用
    @Numbers
    ,第一个例子是有意义的,其中键是数字。然后您可以稍后
    push@{$Numbers[$NumericKey]}、@AdditionalNumbers(请注意,索引序列中有“间隙”是有效的)提示:清空空数组没有意义<代码>我的@Numbers=()简化为
    my@numberRe“圆括号是数组”,完全错误<代码>()
    与数组无关。帕伦夫妇只是像在数学中那样改变优先级。例如,
    my@a=4
    my@a=4..5,等等,我们只在
    my@a=(4,5)中使用它们因为它的意思是
    (my@a=4),5否则<代码>我的@a
    []
    的命名等价物,而不是
    ()
    。是的,未定义的标量就是标量。数组和散列值是标量。@sdp,是的<代码>推送{$Numbers[0]},3,8,9
    实际上是
    push@{$Numbers[0]/=[]}、3、8、9的缩写,我们称之为自生。在底部的解释中缺少了一个步骤,当使用未定义的标量作为引用时,会自动创建一个数组。我不打算这样做,因为我认为这个答案很好地解释了代码的功能。但这不是OP的问题。他们特别询问关于自体移植的问题,而你似乎正在为此而挣扎。我刚刚发布了一个答案。你让我说了11遍“自动激活”。把它改成12。