2

配列への参照を、実行できると理解しているさまざまな方法で使用しようとしています。
これが私の試練の1つです:-

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

ご覧のとおり、3つの異なるアレイがあります。

  • $RoR->2つの匿名配列を含む匿名配列への参照です

  • @AoA->2つの匿名配列を含む配列です。2番目の匿名配列は、参照が指す配列と同じです。$RoR

  • @AwR->とほぼ同じです@AoAが、新しい匿名配列を使用するのではなく、参照@{$RoR}自体をその中に追加した点が異なります。つまり、基本的に、最後の2つの配列は実質的に同じだと思います。

さて、問題は、彼らが同じように振る舞っていないということです。

  • printステートメント1、および2は正常に機能しており5、結果として値を出力します。

  • printステートメント3でエラーが発生しますが、その理由はわかっているので、問題はありません。printステートメント4は、期待どおりに値を出力3しています。

  • さて、プログラムを実行しようとすると、printステートメント56いくつかのエラーがスローされます。

    "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]含むように、に置き換えました@{$RoR}。2つ目は正常に動作していますが、1つ目はまだエラーをスローしています。

1st twoでは、と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.

最初の3つのステートメントは同じを出力してい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.

それで、2つの異なる方法でそれを使用することの違いは何ですか?

4

3 に答える 3

5

割り当てでは@AwR、匿名配列への参照を逆参照する$RoRため、基本的に次の動作が得られます。

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

期待できません:

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

アップデート

多次元配列(配列の配列、AoA)がある場合、最初以降のすべての次元が参照である必要があります。したがって、間接参照矢印を明示的に使用する必要はありませんが、許可されています。したがって、参照としてある場合は、AoA最初の次元の明示性を逆参照する必要があり、2つの方法$$AoAまたは$AoA->で行うことができますが、お気づきのように2回逆参照することはできません($$RoR->[1]例では)。

特定の要素へのアドレスが必要な場合、次の次元では間接参照矢印を省略できます。したがって、2つの同等の使用法があります。

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と同一の配列を作成するには、$RoRを逆参照せずに@AwRを作成します。

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

説明: -

  • 最初の2つのprintステートメントは単純明快です。両方とも値を出力します5
  • 3(a)はコンパイルされません。これは、参照がないと匿名配列のインデックスにアクセスできないためarrowです。
  • 3(b)は機能します。これは、次をreference - $RoR使用して参照を解除したためです。$$RoR

  • 4番目のprintステートメントは、に似ており3(b)、実行していることを実行するための明確な方法3(b)です。は匿名配列への参照であるためRoR、通常の配列のように要素にアクセスすることはできません。矢印(->)を使用する必要があります。ネストされた配列arrowにアクセスするために、任意のレベルにインデックスを追加できます。anonymous

$$RoR[0][1]が機能するのは、右側の演算子よりも左側$RoRのデリファレンスに緊密にバインドするためです。したがって、最初に参照を解除して配列を取得し、次に適用されます。$subscript$RoRsubscript

これがPerlドキュメントからの引用です:-

5つのプレフィックスデリファレンス(誰かが罵倒しているように見える:$ @ *%&)に対するPerlの優先順位規則により、それらは接尾辞の下付き括弧または中括弧よりも緊密にバインドされます。
Perlで一見同等の構造である、$$ aref [$ i]は、最初に$ arefの間接参照を実行し、配列への参照として$ arefを取得し、次にそれを逆参照し、最後にi番目の値を通知します。 $AoAが指す配列

  • 5番目と6番目の印刷ステートメントは3(b)と同様です。$AwR[1]参照$RoRのみが含まれているため。したがって、次の$AwR[1]ように変換されます$$RoR。したがって、5番目のステートメント$AwR[1][0][1]と同様です。$$RoR[0][1]そして、6番目のステートメント:-$AwR[1]->[0][1]は次のように変換されます:- $$RoR->[0][1]。今ここに私の疑問があります。6thステートメントはどのように機能していますか。an arrowで使用できるのはなぜですかde-referenced reference

  • 7thprintステートメントでは、$AwR[1][1]->[1]はに似てい${$RoR}[1]->[1]ます。したがって、添え字演算子の前に参照解除が行われることは明らかです。したがって、参照の2nd後に取得された配列上の要素にアクセスできます。de-referencing$RoR

  • 8th9thprintステートメントはほとんど同じです。また、を参照解除していreference $RoRます。しかし今、私たちはde-referencingではarrayなくになりscalarます。


私はできる限り最善の方法で説明しようとしました。上記の説明に誤りや欠落がある場合は、その点を指摘してください。それは私がもっと学ぶのを助けるでしょう。

また、誰かが説明して、ステートメント5thを印刷することはできますか?6thこれを上記の質問に追加します。

于 2012-10-31T12:13:30.450 に答える