最近perlのスタッシュと言う単語を覚えました。所謂パッケージスコープのシンボルテーブルで特定のパッケージ内に定義されている関数や変数の情報を得る事が出来ます。詳細は以下のページが解り易かったです。
さて問題は何かというと、上記ページにも書かれているように、my変数がスタッシュではなく、別のスクラッチパッドと呼ばれる領域に格納されるため、スタッシュからはアクセスできないという事です。
定義されているmy変数のリストも取得したいと思い調べてみると、PadWalkerというモジュールに行き着きました。このモジュールを使うと、なんとスクラッチパッドの読み書きが出来ます。例えば以下のようにして使用します。
#!/usr/bin/perl
use strict;
use warnings;
use PadWalker qw(peek_my peek_our);
use Data::Dumper;
my $scalar = "hello";
my @list = (1,2,3);
our %hash = (item1 => 'val1', item2 => 'val2');
print Dumper peek_my(0); # このスコープで定義されているmy変数のハッシュを見る
print Dumper peek_our(0); # our変数を見る事も出来る
# ハッシュ経由で変数を弄る事も出来る
${peek_my(0)->{'$scalar'}} .= " world";
print $scalar . "\n"; # hello world
上記プログラムのpeek_my(0)のダンプ結果は以下のようになります。ばっちり思った結果が得られていますね。
$VAR1 = {
'$scalar' => \'hello',
'@list' => [
1,
2,
3
]
};
これでスタッシュ経由でグローバル変数、スクラッチパッド経由でmy変数を、それぞれハッシュで得られるようになりました。だから何だという話もありますが、僕はperlのビギナーなので、Cやjavaの感覚でperlのプログラムを書いて、挙動が思ったようにならない事がよくあります。そんな時にシンボルテーブルどうなってるの?と確認できるのは結構便利です。ここ数時間あれこれダンプしすぎて作業が進みませんが。。
さておまけですが、このPadWalkerを使うと別のスコープのmy変数にアクセスできます。
sub modify_var {
my $var_name = shift;
# peek_my(1)で一つ上のスコープのスクラッチパッドにアクセスできる。
${peek_my(1)->{$var_name}} = "modified";
}
my $data = 'new data';
modify_var('$data');
print $data . "\n"; # modified
こんな事されるとレキシカルスコープ危うしですね。使い道も今のところ思いつきません。