2

我正在尝试以我理解的各种方式使用对数组的引用。
这是我的一个试验:-

my $RoR = [[2, 3], [4, 5, 7]];
my @AoA = ([2, 3], [[2, 3], [4, 5, 7]]);
my @AwR = ([2, 3], @{$RoR});

print $AoA[1][1][1], "\n";      # 1
print $AoA[1]->[1][1], "\n";    # 2

#print $RoR[0][1], "\n";        # 3
print $RoR->[0][1], "\n";       # 4

print $AwR[1][1][1], "\n";          # 5
print $AwR[1]->[1][1], "\n";        # 6

如您所见,我有三个不同的数组。

  • $RoR-> 是对匿名数组的引用,其中包含两个匿名数组

  • @AoA-> 是一个包含 2 个匿名数组的数组。第二个匿名数组与引用指向的数组相同$RoR

  • @AwR-> 与 几乎相同@AoA,但不同之处在于,我没有使用新的匿名数组,而是在其中添加了引用@{$RoR}本身。所以,基本上我认为,最后两个数组实际上是相同的。

现在,问题是,他们的行为方式不同

  • 打印语句1,并且2工作正常,并打印出值5作为结果。

  • 打印语句3给出错误,我知道为什么,所以没有问题。正如预期的那样,print 语句4正在打印 value 。3

  • 现在,当我尝试运行程序时,打印语句5和抛出一些错误。6

    "Can't use string ("2") as an ARRAY ref while \"strict refs\" in use at 
    D:/_Perl Practice/3perldsc/array_of_array.pl line 15."
    

然后我尝试使用: -

print $AwR[1][1]->[1], "\n";    
print @{$RoR}[1]->[1];

在哪里,我$AwR[1]@{$RoR}, 替换为$AwR[1]contains @{$RoR}。第二个工作正常,而第一个仍然抛出错误。

1st two那么,the和last twoprint 语句之间究竟有什么区别呢?我认为它们是相同的,因此应该为相同的索引访问提供相同的结果。但事实并非如此。我是否以某种错误的方式使用了参考?


好的,现在上面的疑问很清楚了。所以,我发布了一个答案,积累了与这个问题相关的一般内容。请看下面。在那,我对5th and 6th打印语句有疑问,为了理解它,我尝试了以下测试: -

print $AwR[1][1];   # Allowed as `$AwR[1]` is same as `$$RoR`.
print $$RoR[1];     # Allowed as in 3(b)
print $AwR[1]->[1]; # Confused here. It is allowed
print $$RoR->[1];   # But this is not.

前三个语句打印相同reference value。但最后一个失败了。因此,可以肯定 :-$AwR[1]$$RoR. 但是,为什么$$RoR->[1]工作时$AwR[1]->[1]不工作?它向我抛出了这个错误:-

Not a SCALAR reference at D:/_Perl Practice/3perldsc/array_of_array.pl line 24.

那么,以两种不同的方式使用它有什么区别呢?

4

3 回答 3

5

在分配给@AwR您时取消引用您对匿名数组的引用$RoR,因此您基本上会得到以下行为:

my @AwR = ([2, 3], [2, 3], [4, 5, 7]);

没想到:

my @AwR = ([2, 3], [[2, 3], [4, 5, 7]]);

更新

如果我们有多维数组(array of arrays,AoA),那么 first 之后的每个维度都必须是一个引用。所以没有必要显式地使用解引用箭头,但它是允许的。所以,如果我们有AoA作为参考,我们需要取消引用第一维显式,我们可以通过两种方式$$AoA$AoA->,但我们不能像你注意到的那样取消引用它两次($$RoR->[1]在你的例子中)。

当我们需要对某个元素的地址时,我们可以省略任何以下维度的取消引用箭头,因此有两种等效用法:

my @AoA = ([2, 3], [ [2, 3], [4, 5, 7, [11, 12, [111, 112] ] ] ], [0]);
print "A: $AoA[1][1][3][2][0] \n";          # == 111
print "B: $AoA[1]->[1]->[3]->[2]->[0] \n";  # == 111

AoA作为参考

my $AoA = [ [2, 3], [ [2, 3], [4, 5, 7, [11, 12, [111, 112] ] ] ], [0] ];
print "A: $$AoA[1][1][3][2][0] \n";           # == 111
print "B: $AoA->[1]->[1]->[3]->[2]->[0] \n";  # == 111
于 2012-10-31T11:13:02.473 回答
3

您似乎期望@AoA 和@AwR 是相同的,但事实并非如此。您可以通过一个简单的测试脚本看到这一点:

#!/usr/bin/perl

use strict;
use warnings;
use Test::More;

my $RoR = [[2, 3], [4, 5, 7]];
my @AoA = ([2, 3], [[2, 3], [4, 5, 7]]);
my @AwR = ([2, 3], @{$RoR});

is_deeply(\@AwR, \@AoA, 'arrays match');

这是因为您将 $RoR 插入 @AwR 的方式。要创建与 @AoA 相同的数组,请创建 @AwR 而不取消引用 $RoR:

my @newAwR = ([2, 3], $RoR);

并测试以确认这是正确的:

is_deeply(\@newAwR, \@AoA, 'arrays match');
于 2012-10-31T11:18:28.430 回答
1

好的,既然我已经弄清楚了,我想我会发布我的答案:-

use strict;
use warnings;
use Test::More;

my $RoR = [[2, 3], [4, 5, 7]];
my @AoA = ([2, 3], [[2, 3], [4, 5, 7]], [0]);
my @AwR = ([2, 3], $RoR, [0]);

print "1: ", $AoA[1][1][1], "\n";       # 1
print "2: ", $AoA[1]->[1][1], "\n";     # 2

#print "3(a): ", $RoR[0][1], "\n";      # 3(a) 
print "3(b): ", $$RoR[0][1], "\n";      # 3(b)          
print "4: ", $RoR->[0][1], "\n";        # 4

print "5: ", $AwR[1][0][1], "\n";       # 5
print "6: ", $AwR[1]->[0][1], "\n";     # 6

print "7: ", $AwR[1][1]->[1], "\n";     # 7
print "8: ", @{$RoR}[1]->[1], "\n";     # 8
print "9: ", @{$AwR[1]}[1]->[1], "\n";  # 9

解释: -

  • 前两个打印语句是直截了当的。他们都将打印价值5
  • 3(a) 将无法编译,因为我们无法在没有arrow.
  • 3(b) 有效,因为现在,我们已经reference - $RoR通过使用取消引用我们的$$RoR

  • 第 4 条打印语句,类似于3(b), 并且是一种清晰的方式来做3(b)正在做的事情。因为RoR是对匿名数组的引用,所以我们不能像普通数组那样访问元素。我们必须使用箭头 ( ->)。之后arrow我们可以将索引添加到任何级别以访问嵌套anonymous数组。

$$RoR[0][1]之所以有效,是因为它与左侧$RoR的取消引用器绑定比与右侧的运算符更紧密地绑定。因此,首先取消引用以获取数组,然后再应用。$subscript$RoRsubscript

这是Perl 文档的引用:-

Perl 对其五个前缀解引用器的优先级规则(看起来像是有人在发誓:$ @ * % &)使它们比后缀下标括号或大括号绑定得更紧密。
Perl 中看似等效的构造,$$aref[$i] 首先对 $aref 进行 deref,使其将 $aref 作为对数组的引用,然后取消引用,最后告诉你第 i 个值$AoA 指向的数组

  • 第 5 条和第 6 条打印语句与 3(b) 类似。由于仅$AwR[1]包含参考$RoR。因此,$AwR[1]转换为:$$RoR. 因此,$AwR[1][0][1]类似于$$RoR[0][1]第 5 条语句。第 6 条语句: -$AwR[1]->[0][1]被转换为: - $$RoR->[0][1]。现在这是我的疑问。声明是如何6th工作的。为什么我们可以an arrowde-referenced reference.

  • 7thprint 语句中,$AwR[1][1]->[1]类似于${$RoR}[1]->[1]. 因此,很明显,取消引用是在下标运算符之前完成的。因此,我们可以访问在引用2nd之后获得的数组上的元素。de-referencing$RoR

  • 8th9th打印语句几乎相同。此外,我们正在取消引用reference $RoR. 但是现在,我们de-referencing要的是arraya 而不是 a scalar


我试图以最好的方式解释。以上说明如有错误或遗漏,请指出。这将帮助我了解更多。

另外,有人可以解释一下5th6th打印声明。我将把它添加到上面的问题中。

于 2012-10-31T12:13:30.450 回答