2006 年 5 月 1 日 23 時 11 分

シンボルの列挙


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


では、シンボルテーブルからコードを検索してみよう。
例えば、Carp のシンボルテーブルを調べてみる。

    use Carp;

まずはシンボルテーブルを取得する。

    my $package = 'Carp';
    no strict 'refs';
    my $symbol_table = \%{"${package}::"};
    use strict 'refs';

今後のために、シンボリックリファレンスを使って、
シンボルテーブルを取得してみた。
シンボルテーブルは連想配列であるので、
each を使えば中身を列挙できる。

    while ( my ($key, $value) = each %$symbol_table) {
        # シンボルごとの処理。
    }

シンボルテーブルの中身は、原則として型グロブである。
関数のプロトタイプとの兼ね合いで、例外もありえるので、
型グロブであるかどうか調べる必要がある。

        # 型グロブでない場合は抜ける。
        next if ref \$value ne 'GLOB';

型グロブが見つかった場合、コード用のスロットを調べる。
メソッドや関数があれば、リファレンスが格納されている。
逆に定義されていなければ、undef となる。

        # コードが格納されていなければ抜ける。
        next if not defined *$value{'CODE'};

コードリファレンスが取れれば、メソッドが定義されている。
見つかったメソッドを画面に出力してみよう。

        # 名前を出力。
        print "\&$key\n";

では、上記をまとめてテストしてみよう。

========== dumpcode.pl ==========

use strict;
use warnings;
use Carp;

sub dump_code {
    my $package = $_[0];

    no strict 'refs';
    my $symbol_table = \%{"${package}::"};
    use strict 'refs';

    while ( my ($key, $value) = each %$symbol_table) {
        next if ref \$value ne 'GLOB';
        next if not defined *$value{'CODE'};
        print "\&$key\n";
    }
}

dump_code('Carp');

========== end of dumpcode.pl ==========

$ perl ./dumpcode.pl
&export_fail
&shortmess
&longmess
&croak
&confess
&carp
&cluck

俺の環境ではこのようになった。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.