アルパカ三銃士

〜アルパカに酔いしれる獣たちへ捧げる〜

Package::Stash という凄そうなやつ

先日このようなツイートをした

Package::Stash というモジュールの詳細は以下のリンクから

metacpan.org

このモジュールは Perl の黒魔術によく使われるスタッシュをシンプルに使えるようにモジュール化したものである。

スタッシュ(よくシンボルテーブルと言われる)というのは、各パッケージの情報をシンボルという形で保存するハッシュのことを指し、次のようなシンボルが存在する。

具体的に、例えば以下のようにパッケージ Hello を定義した時、そのパッケージのシンボルテーブル一覧を取得したい場合は次のように行うことが可能である。

package Hello;

our $a = 10;

our %hash = (a => 10);

sub new {
    my $class = shift;
    return bless +{}, $class;
}

sub pow {
    my ($self, $msg) = @_;
    print "Pow: $msg";
}

package main;

use Data::Dumper;

print Dumper \%Hello::;

これの結果は次のようになる。

$VAR1 = {
          'a' => *Hello::a,
          'hash' => *Hello::hash,
          'pow' => *Hello::pow,
          'new' => *Hello::new
        };

こんな感じに取得をすることが可能であるが、どうも黒魔術臭いためチームで共有するためのコードを書くとなると、若干きつい感じがする。
そこで Package::Stash の出番となる。

package Hello;

our $a = 10;

our %hash = (a => 10);

sub new {
    my $class = shift;
    return bless +{}, $class;
}

sub pow {
    my ($self, $msg) = @_;
    print "Pow: $msg";
}

package main;
use Package::Stash;
use Data::Dumper;

my $stash = Package::Stash->new('Hello');
print Dumper $stash->get_all_symbols;

このように通常の Perl コードを記述するように書けるが、結果はちゃんと上記と同じようになる。
もちろんシンボルテーブルにアクセスができるため、次のようなこともできる。

#!/usr/bin/env perl

use strict;
use warnings;
use Package::Stash;

package main;

use Data::Dumper;

my $stash = Package::Stash->new('Data::Dumper');
my $syms = $stash->get_all_symbols;

# print Dumper $syms;

my $hs = +[1..10];
print $syms->{Dumper}($hs);

このコードは Data::Dumper のスタッシュを取得し、Dumper のシンボルへアクセスすることによってルーチンの呼び出しを行うことができている。