Symbolic reference(シンボリックリファレンス)

変数の名前への参照

一般的にリファレンスといえばハードリファレンスを指しますが、それはスカラー変数の値などの実体への参照を指します。 ところが、シンボリックリファレンスの参照先は実体ではなく、シンボル(変数などの名前)という点が大きく異なります。 次はシンボリックリファレンスの簡単な例です。

# 変数の名前を定義
my $valname = 'firstname';

# シンボリックリファレンスを通して変数 $firstname に値をセット
${$valname} = 'Taro';

# シンボリックリファレンスを通して $firstname の値を出力
print ${$valname}, "\n";    # Taro

# ダイレクトに $firstname の値を出力
print $firstname, "\n";    # Taro

上記コードでは、スカラー変数 $valname に変数名となる文字列をセットしています。 次に、${$valname} に文字列 "Taro" をセットしています。 これはシンボリックリファレンスを通して変数 $firstname に値をセットたことになります。 次に、$$valname の値を出力していますが、これはシンボリックリファレンスを通して $firstname の値を出力していることになります。 最後に $firstname を出力しています。いずれも "Taro" が出力されます。

前述の例は、シンボリックリファレンスを通して新たな変数 ($firstname) を作って、 その値を読み取っていましたが、すでに定義された変数を、 シンボリックリファレンスを通して値を読み取るということはできませんので注意してください。

# 変数を定義
my $firstname = 'Taro';

# 変数の名前を定義
my $valname = 'firstname';

# シンボリックリファレンスを通して $firstname の値にアクセスするつもりが、
# 実際にはハードリファレンスのデリファレンスとして解釈されるため、
# 結果的に何も出力されない(undef が返ってくる)
print ${$valname}, "\n";

もし動的に変数名を指定したいなら、evaleval EXPR 構文を使うべきでしょう。

# 変数を定義
my $firstname = 'Taro';

# 変数の名前を定義
my $valname = 'firstname';

# 変数 $valname が展開されて print $firstname が実行される
eval "print \$$valname";    # Taro

シンボリックリファレンスはハードリファレンスと区別しづらいため、コードの保守性がとても悪くなります。 そのせいもあって、use strict 環境ではシンボリックリファレンスは無効になっています。 もし、strict モードをリファレンス関連だけに限定したいなら次のようにします。

use strict 'refs'

逆に特定のブロックの中だけでシンボリックリファレンスを使えるようにすることもできます。

no strict 'refs';