PadWalkerでmy変数のシンボルテーブルを取得する

最近perlのスタッシュと言う単語を覚えました。所謂パッケージスコープのシンボルテーブルで特定のパッケージ内に定義されている関数や変数の情報を得る事が出来ます。詳細は以下のページが解り易かったです。

wakaponさんの備忘帳

さて問題は何かというと、上記ページにも書かれているように、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

こんな事されるとレキシカルスコープ危うしですね。使い道も今のところ思いつきません。

Leave a Reply

Your email address will not be published. Required fields are marked *