配列の配列、ハッシュのハッシュ、その他の複雑なデータ構造は、Perlでは参照を使用して構築されています。このアプローチにより、階層的/分岐構造を容易に作成できますが、アクセス、コピー、変更時には注意が必要です。デフォルトでは、実際の内容ではなく参照が保持されます。
もともとPerlはフラットな配列とハッシュのみをサポートしており、ネストはありませんでした。その後、参照のサポートが追加され、配列の配列、ハッシュのハッシュ、"木"、"グラフ"など、あらゆる組み合わせが作成可能になりました。
複雑な構造で作業するには、アクセス、書き込み、コピーの操作が参照で動作することを覚えておく必要があります。エラーは、要素と要素への参照との混乱から頻繁に発生します。これにより、プログラムの異なる部分が同時に参照を使用する場合、ある場所でのデータの変更がすべての構造に反映されるなど、多くのバグが生じます。
配列の配列を作成するには:
my @matrix; for my $i (0..2) { for my $j (0..2) { $matrix[$i][$j] = $i * $j; } } print $matrix[1][2]; # 2
ハッシュのハッシュの場合:
my %data; $data{'user1'}{'name'} = 'Alex'; $data{'user1'}{'age'} = 20;
混合構造:
my %complex = ( 'list' => [1, 2, 3], 'map' => { foo => 'bar' }, );
構造をコピーするために、一つの配列を別の配列に代入するとどうなりますか?
そのような代入はネストされた構造をコピーせず、参照だけがコピーされます(すなわち "浅いコピー" が行われます)。
my @a = ([1,2], [3,4]); my @b = @a; $a[0][0] = 99; printf "$b[0][0] "; # 99が出力されます、@bは@aと同じ配列への参照を含んでいるため
$array[$i] と $array->[$i] で要素にアクセスすることの違いは何ですか?
最初の形式は配列の場合に機能し、2番目の形式は配列を参照するスカラの場合に機能します。ネストされた構造には、最も一般的な構文は矢印形式($foo->[0])です。
標準のPerlでdcloneを使って単に構造のコピーを取ることができないのはなぜですか?
dcloneはPerlの基本パッケージには含まれていないためです。複雑な構造の深いコピーにはStorableモジュールとdclone関数を使用します:
use Storable 'dclone'; my $deep_copy = dclone(\%complex);
プロジェクトでは、配列の配列を通常の代入(@copy = @org)でコピーし、その後の変更の後にデータの"オリジナル"がコピーと一緒に変わったことに気づきました。
利点:
欠点:
Storableモジュールとdclone関数を使用して配列とハッシュをコピーし、コード内でこれを明示的に文書化し、参照と非参照を明示的に区別します。
利点:
欠点: