数组推送和引用
Array push and references
我是一个初学者 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]}
的目的。推送是否会自动在 Numbers
数组中创建对 [3,8,9]
和 [5]
的数组引用?我不难理解下面的语法,我想这更常见,但我没有遇到我在上面粘贴的语法,我猜它也使用自动激活来填充带有引用的 Numbers 数组。
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
];
如果将数组传递给 Dumper,元素将被解释为多个参数。
圆括号是数组,方括号是数组引用。 push
仅适用于数组,不适用于数组引用。有关引用和取消引用的详细信息,请参阅 Perl 手册 perlref。
您可以使用反斜杠将数组转换为数组引用:
print Dumper(\@Numbers);
现在 Dumper 显示带有方括号的引用。
$VAR1 = [
[
3,
8,
9
],
[
5
]
];
您也可以将 Numbers 设为引用,但在将其传递给 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
附加到取消引用的数组。
这导致创建数组引用。
有两个特征在起作用,其中一个确实是 autovivification。
稍后我将进入自动复活。首先,让我们考虑这样一个事实,即当我们访问 $Numbers[0]
时 @Numbers
是空的。这不是问题。 Perl 将自动扩展数组以包含此元素。[1]
my @a;
$a[3] = 123; # ok!
print(Dumper(\@a)); # [ undef, undef, undef, 123 ]
这不是文档中所说的自动生成,但它非常相似,以至于有些人也将其称为自动生成。
正如我提到的,第二个功能确实是自动生成。 Autovivification 是通过取消引用自动创建匿名变量。具体来说,它发生在取消引用未定义的标量时。[2]
在这种情况下,自动生成会创建一个数组,因为 @BLOCK
是一个数组解引用。对该数组的引用被创建并存储在以前的 undef 标量中。
换句话说,自动生成
push @{ $ref }, LIST;
实际上等同于
push @{ $ref //= [] }, LIST;
或
if (!defined($ref)) {
my @anon;
$ref = \@anon;
}
push @$ref, LIST;
这可能只是该问题的人为示例,但请注意,发布的代码很奇怪。我们知道 $Numbers[0]
和 $Numbers[1]
是 undef,所以我们不需要 push
.
my @nums;
@{ $nums[0] } = ( 3, 8, 9 ); # Also autovivification.
@{ $nums[1] } = 5;
并且因为我们知道 $Numbers[0]
和 $Numbers[1]
是 undef,我们也没有必要依赖自动生成。
my @nums;
$nums[0] = [ 3, 8, 9 ];
$nums[1] = [ 5 ];
让我们摆脱那些硬编码的索引。
my @nums;
push @nums, [ 3, 8, 9 ];
push @nums, [ 5 ];
最后的简化。
my @nums = (
[ 3, 8, 9 ],
[ 5 ],
);
这只发生在左值上下文中,这意味着引用的变量应该是 modified/modifiable。 say $a[@a];
不会扩展数组,即使它访问最后一个元素之后的元素。
它也必须在左值上下文中。 my @copy = @{ $undef };
不会自动激活。
我是一个初学者 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]}
的目的。推送是否会自动在 Numbers
数组中创建对 [3,8,9]
和 [5]
的数组引用?我不难理解下面的语法,我想这更常见,但我没有遇到我在上面粘贴的语法,我猜它也使用自动激活来填充带有引用的 Numbers 数组。
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
];
如果将数组传递给 Dumper,元素将被解释为多个参数。
圆括号是数组,方括号是数组引用。 push
仅适用于数组,不适用于数组引用。有关引用和取消引用的详细信息,请参阅 Perl 手册 perlref。
您可以使用反斜杠将数组转换为数组引用:
print Dumper(\@Numbers);
现在 Dumper 显示带有方括号的引用。
$VAR1 = [
[
3,
8,
9
],
[
5
]
];
您也可以将 Numbers 设为引用,但在将其传递给 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
附加到取消引用的数组。
这导致创建数组引用。
有两个特征在起作用,其中一个确实是 autovivification。
稍后我将进入自动复活。首先,让我们考虑这样一个事实,即当我们访问 $Numbers[0]
时 @Numbers
是空的。这不是问题。 Perl 将自动扩展数组以包含此元素。[1]
my @a;
$a[3] = 123; # ok!
print(Dumper(\@a)); # [ undef, undef, undef, 123 ]
这不是文档中所说的自动生成,但它非常相似,以至于有些人也将其称为自动生成。
正如我提到的,第二个功能确实是自动生成。 Autovivification 是通过取消引用自动创建匿名变量。具体来说,它发生在取消引用未定义的标量时。[2]
在这种情况下,自动生成会创建一个数组,因为 @BLOCK
是一个数组解引用。对该数组的引用被创建并存储在以前的 undef 标量中。
换句话说,自动生成
push @{ $ref }, LIST;
实际上等同于
push @{ $ref //= [] }, LIST;
或
if (!defined($ref)) {
my @anon;
$ref = \@anon;
}
push @$ref, LIST;
这可能只是该问题的人为示例,但请注意,发布的代码很奇怪。我们知道 $Numbers[0]
和 $Numbers[1]
是 undef,所以我们不需要 push
.
my @nums;
@{ $nums[0] } = ( 3, 8, 9 ); # Also autovivification.
@{ $nums[1] } = 5;
并且因为我们知道 $Numbers[0]
和 $Numbers[1]
是 undef,我们也没有必要依赖自动生成。
my @nums;
$nums[0] = [ 3, 8, 9 ];
$nums[1] = [ 5 ];
让我们摆脱那些硬编码的索引。
my @nums;
push @nums, [ 3, 8, 9 ];
push @nums, [ 5 ];
最后的简化。
my @nums = (
[ 3, 8, 9 ],
[ 5 ],
);
这只发生在左值上下文中,这意味着引用的变量应该是 modified/modifiable。
say $a[@a];
不会扩展数组,即使它访问最后一个元素之后的元素。它也必须在左值上下文中。
my @copy = @{ $undef };
不会自动激活。