参照とデータ構造

[1] はじめに

参照(reference)と呼ばれる特別な変数についての解説です。参照はスカラー変数です。

[2] 参照の生成と逆参照

参照(reference)の生成と逆参照(dereferencing)の仕方を例を用いて説明します。

例では _ref を含む名前の変数が参照です。

生成された参照を参照のインスタンスと呼ぶことがあります。

[3] スカラーへの参照

# 参照の生成
$scalar = "Hello, world!";
$scalar_ref = \$scalar;

$scalar_ref2 = \3.14;

# 参照の逆参照
# 下の文は何れも Hello, world! を出力。
print $$scalar_ref;
print ${ $scalar_ref };

[4] 配列への参照

# 参照の生成
@array = ("Apple", "Banana", "Orange");
$array_ref = \@array;

$array_ref2 = ["Dog", "Cat", "Bird"];

# 参照の逆参照
# 下の文は何れも、AppleBananaOrange を出力。
print @$array_ref;
print @{ $array_ref };

# 下の文は何れも、Apple を出力。
print $$array_ref[0];
print ${ $array_ref }[0];
print $array_ref->[0];

# 下の文は、BananaOrange を出力。
print @$array_ref[1..2];

[5] ハッシュへの参照

# 参照の生成
%hash = (
         Name => 'Suzuki',
         Age => 40,
         Job => 'Teacher',
         );
$hash_ref = \%hash;

$hash_ref2 = {
    Name => 'Tanaka',
    Age => 20,
    Job => 'None',
};

# 参照の逆参照
# 下の文は何れも、Age40JobTeacherNameSuzuki を出力。

print %$hash_ref;
print %{ $hash_ref };

# 下の文は Suzuki を出力します。
print $$hash_ref{Name};
print $hash_ref->{Name};

[6] サブルーチンへの参照(コード参照)

# 参照の生成
sub code {
    return $_[0] + $_[1];
}
$code_ref = \&code;

$code_ref2 = sub {
    return $_[0] + 100;
    };

# 参照の逆参照
# 下の文は何れも 7 (3 と 4 の和)を出力。
print &$code_ref(3,4);
print $code_ref->(3,4);

[7] 矢印演算子

以上の例から分かるように、逆参照は
-> の後に [ ] が来る時は、配列への参照の逆参照であり、
-> の後に { } が来る時は、ハッシュへの参照の逆参照であり、
-> の後に ( ) が来る時は、コード参照の逆参照です。

-> は矢印演算子(arrow operator)と呼ばれます。

[8] データ構造

Perl では配列、ハッシュを複雑に入れ子にすることによりデータ構造を実現できます。 例えば配列の配列(二次元配列)、配列の配列の配列(三次元配列)、ハッシュの配列、配列のハッシュ、ハッシュのハッシュ、等等。

以下では配列の配列、ハッシュの配列だけを例にとって、データ構造の生成と逆参照の仕方を説明しますが、配列のハッシュやハッシュのハッシュについても同様にできるはずです。

補足事項としてサブルーチンの配列についても述べます。

[9] 配列の配列

配列の配列(二次元配列)は、Perlでは配列の参照(スカラー値)を配列することにより実現できます。

@x = (
      [3, 4, 5],
      [2, 4, 6],
      [1, 2, 4],
      );

$x_ref = [
          [3, 4, 5],
          [2, 4, 6],
          [1, 2, 4],
          ];

下の文は何れも 5 を出力します。

print $x[0]->[2];
print $x[0][2];              # [ ] の直後の -> を省略できます

print $x_ref->[0]->[2];
print $x_ref->[0][2];        # [ ] の直後の -> を省略できます

[10] ハッシュの配列

ハッシュの配列は、Perlではハッシュへの参照を配列することにより実現できます。

@y = (
      { Name => 'Abe', Age => '23' },
      { Name => 'Iida', Age => '23' },
      { Name => 'Kago', Age => '17' },
      );

$y_ref = [
          { Name => 'Abe', Age => '23' },
          { Name => 'Iida', Age => '23' },
          { Name => 'Kago', Age => '17' },
          ];

下の文はいずれも Abe を出力します。

print $y[0]->{Name};
print $y[0]{Name};              # [ ] の直後の -> を省略できます
print $y_ref->[0]->{Name};
print $y_ref->[0]{Name};        # [ ] の直後の -> を省略できます

[11] サブルーチンの配列

サブルーチンへの参照(コード参照)を配列することにより、「サブルーチンの配列」も可能です。

@z = (
      sub { return 1 + 2 },
      sub { return 'Hello, World!' },
      sub { return $_[0] + $_[1] },
      );

$z_ref = [
          sub { return 1 + 2 },
          sub { return 'Hello, World!' },
          sub { return $_[0] + $_[1] },
          ];

下の文は何れも 3 ( = 1 + 2 ) を出力します。

print &{$z[0]};
print $z[0]->();

print &{$z_ref->[0]};
print $z_ref->[0]->();
print $z_ref->[0]();            # [ ] の直後の -> を省略できます

下の文は何れも 7 ( = 3 + 4) を出力します。

print &{$z[2]}(3,4);
print $z[2]->(3,4);

print &{$z_ref->[2]}(3,4);
print $z_ref->[2]->(3,4);
print $z_ref->[2](3,4);         # [ ] の直後の -> を省略できます