変数の名前への参照
一般的にリファレンスといえばハードリファレンスを指しますが、それはスカラー変数の値などの実体への参照を指します。 ところが、シンボリックリファレンスの参照先は実体ではなく、シンボル(変数などの名前)という点が大きく異なります。 次はシンボリックリファレンスの簡単な例です。
# 変数の名前を定義
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";
もし動的に変数名を指定したいなら、eval
の eval EXPR
構文を使うべきでしょう。
# 変数を定義
my $firstname = 'Taro';
# 変数の名前を定義
my $valname = 'firstname';
# 変数 $valname が展開されて print $firstname が実行される
eval "print \$$valname"; # Taro
シンボリックリファレンスはハードリファレンスと区別しづらいため、コードの保守性がとても悪くなります。
そのせいもあって、use strict
環境ではシンボリックリファレンスは無効になっています。
もし、strict モードをリファレンス関連だけに限定したいなら次のようにします。
use strict 'refs'
逆に特定のブロックの中だけでシンボリックリファレンスを使えるようにすることもできます。
no strict 'refs';