Perl Hackers Hub

第19回 Acmeで広がるPerlの世界―CPANは愉快なジョークモジュールの宝庫(2)

この記事を読むのに必要な時間:およそ 6 分

まだまだたくさんあるよ! Acmeモジュール

ほかにもたくさんあるAcmeモジュールの中から,本当に一部ですがお勧めのものを表1にまとめました注3)⁠ここに挙げたもののいくつかは,よそでも紹介されている有名なものです。ぜひ実際にインストールして動作を確かめてみてください。

表1 お勧めAcmeモジュール

モジュール名機能の概要
Acme::Bleach1回目の起動でソースコードを半角スペースとタブの2値に変換して「真っさら」⁠漂白=bleach)にする。2回目以降の呼び出しでは,内部で元のソースコードに戻すので元どおり動作する。モールス信号に変換するAcme::Morseなども同梱されている。最初のAcmeモジュール
Acme::Boomuseするとセグメンテーション違反(不正なメモリアクセス)を発生させエラーを引き起こす。同梱のテストファイルでは$SIG{SEGV}を使うことでエラーをトラップして動作確認をしている。ほかにAcme::Segvというモジュールもあるが,こちらはうまくエラーを起こしてくれないことが多い
Acme::Code::Policeこのモジュールがuseされたスクリプト内でuse strictをしていなかったら,そのファイルを削除する! まさにコードの治安維持者!
Acme::Code::FreedomFighter上述のAcme::Code::Policeがuse strictしていないファイルを削除しようしたとき,逆にAcme::Code::Policeモジュールを削除する! まさに自由のための闘士!
Acme::Damnblessされたオブジェクトを通常のオブジェクトに戻す。CPANモジュール中,厳密な意味でblessを解除する方法を提供しているモジュールはこれだけである。たいへん貴重な,Acmeじゃないパッケージの依存モジュールになっているAcmeモジュール
Acme::FizzBuzzuseするだけでFizzBuzz問題(整数の1から順に表示していき,3で割り切れるならFizz,5で割り切れるならBuzz,両方で割り切れるならFizzBuzzと表示するゲーム)を解決する
Acme::GodotSamuel Beckettの戯曲「ゴドーを待ちながら」よろしく,ゴドーを待ち続ける。内部的にはゴドーが来たかどうか判定し(常に偽値を返す)⁠来なかったら約1年間sleepする。以上を繰り返す
Acme::MathProfessor::RandomPrime典型的な数学の教授が素数を取り上げる際に採用するアルゴリズムに基づいて,素数を返す。なんだかすごそうだが実は素数の17か23を返すだけ
Acme::MetaSyntacticfoo,barなどといった変数の名前を考えてくれる。膨大な数のカテゴリから選べるので便利
Acme::MorningMusumeアイドルグループ「モーニング娘。」のデータを取得できる。CPANにはほかにもAcme::MomoiroClover(ももいろクローバーZ)やAcme::PrettyCure(アニメ「プリキュア」シリーズ)などアイドルのデータ取得系モジュールが存在する
Acme::Math::PerfectChristmasTree高さ(cm)を与えると最適なクリスマスツリーの飾り付けに必要な道具(電飾とか頂上の☆とか)の長さを計算してくれる
Acme::POE::Treeコンソールにカラフルなクリスマスツリーが表示される。チカチカ光る
Acme::PricelessMethodsis_perl_installed(今使ってるマシンにPerlがインストールされているかどうか)やis_true_true(真値は真値であるか)⁠universe_still_exists(宇宙はまだ存在しているか)などの極めて重要な真偽判定メソッドを提供する,真にプライスレスなモジュールである
Acme::Pythonuseするとソースコードが"hiss"という文字列(蛇(ニシキヘビ=python)「シャー」という音)に変換される。Acme::Bleach同様,2回目の起動以降は本来の動作をする。今年が巳年なので取り上げてみた
Acme::Sneeze::JPsneeze(くしゃみ)というメソッドを提供する。sneezeメソッドを呼び出すと参照アカウントが0にならない(誰かに噂されている)ので,ガベージコレクトの対象にならずメモリリークできる。Acme::Sneezeというモジュールもあり,こちらはAcme::Sneeze::JPとはまた違う動作をする
Acme::Takahashi::Methodソースコードを1行ごとに画面一杯に表示してくれる(みんな大好き「高橋メソッド」⁠すべてのスライドが終了したらプログラムが実行される
Acme::Tpyo与えた文字列をtypo(タイプミス)されたものにして返す。このモジュールの名前もtypoしている
Plack::Middleware::Acme::PHPE9568F
34::D428::11d2::A769::00AA001ACF42
PHPに実装されている,クエリに"?=PHPE9568F34-D428-11d2-A769-00AA001ACF42"を付けるとロゴが表示される機能をPlackミドルウェアとして実現している
Plack::Middleware::Acme::Werewolf満月の日に狼人間がWebサイトにアクセスできないようにする(強制的に403Forbiddenを表示)⁠もともとApache用モジュールだったAcme::Apache::WerewolfをPlackミドルウェアに移植したもの

Acme::MomoiroCloverパッケージ内にAcme::MomoiroClover::Zが同梱されている

注3)
2013年1月上旬時点のものです。

AcmeモジュールからPerlの小技を学ぶ

さて,単におもしろモジュールの紹介だけでは寂しいので,ここからはAcmeモジュールを肴(さかな)に,@INCのフック,lvalueサブルーチン,そしてtie変数といった普段あまり使わない(かもしれない)Perlの機能について学んでいきます。

Acme::Anythingで学ぶ@INCのフック

Acme::Anythingというモジュールをuseすると,どんなモジュールでもuse(あるいはrequire)できるようになります。

リスト5で本来ならば存在しないモジュールYasukute OishiiIwashiをuseするとCan't locate Yasukute OishiiIwashi.pm in @INC ...というエラーが発生します。しかしこのソースを実行してみると,useに失敗しないで最後まで処理が進みます。

リスト5 Acme::Anythingを使ったコード

use Acme::Anything;
use YasukuteOishiiIwashi; # ← 実在しないモジュール
print "ok, this code didn't die.\n";
$ perl acme_anything.pl
ok, this code didn't die.
@INCにはライブラリまでのパスが入っている

ではこのモジュールはどのようなしくみで動いているのか,Acme::Anythingのソースコードを見てみますリスト6)⁠

リスト6 Acme::Anythingのソース(抜粋)

package Acme::Anything;

# 中略

push @main::INC, \&handler_of_last_resort; #  (1)

sub handler_of_last_resort {
    my $fake_source_code = '1';
    open my ($fh), '<', \$fake_source_code; #  (2)
    return $fh;
};

(1)で配列@INCにサブルーチンのリファレンスを挿入しています。perlはモジュールを呼び出すとき,そのモジュールの場所を配列@INCの先頭から順に調べていきます。ですから@INCには通常,モジュールまでのパスが入っています図4)⁠

図4 配列@INCの中身を確認

% perl -E'say $_ for @INC'
/home/makamaka/perlbrew/perls/perl-5.14.2/...
..
@INCにコードリファレンスを入れると……

しかし@INCには,パス代わりにサブルーチンのリファレンスやblessされたオブジェクトを入れることができます。その場合,perlはパスをチェックするのではなく,そのコード(blessされたオブジェクトならINCメソッド)を実行します。実行されたコードには自分自身とモジュール名が引数として渡されます。また,このコードはopenしたモジュールのファイルハンドルを返さなければなりませんリスト7)⁠詳しくはコマンドラインからperldoc -f requireしてみてください。

リスト7 一般化した@INCフック用サブルーチン

sub INC {
    my ( $self, $module_name ) = @_;
    my ( $filename = $module_name . '.pm' ) =~ s{::}{/}g;
    open( my $fh, '<', "$YOUR_LIB_PATH/$filename" )
        or die "Can't locate $filename in $YOUR_LIB_PATH";
    # %INC に何らかの値(通常はファイルまでのパス)を入れる
    $INC{ $filename } = "$YOUR_LIB_PATH/$filename";
    return $fh;
}

リスト6のAcme::Anythingのコードでもファイルハンドル$fhを返していますが,注意しておきたいのは,リスト6(2)の\$fake_source_code です。これは文字列'1'が代入されたスカラ変数のリファレンスです。openの第3引数にスカラリファレンスを渡すと,参照先の文字列を内容とするファイルとみなされます。つまり$fhは1という文字だけが書かれたファイルのファイルハンドルとして扱われます。perlが@INCのパスから指定されたモジュールを見つけられなかったとき,@INCの最後に挿入されたhandler_of_last_resortが実行され,"1"というソースコードのモジュールを読み込んだことになります。このおかげでuseしてもエラーにならないのです。

@INCを利用したAcmeモジュールたち

このように@INCに細工を仕込むAcmeモジュールを表2にまとめました。現在CPAN上にはほかに6個あります。ネタを仕込むのに好都合な機能であることがうかがえますね。

以上,Acmeモジュールから学ぶ@INCのフックでした。

表2 @INCを利用したAcmeモジュール

モジュール名機能の概要
Acme::Incorporated一定の確率でuseしたモジュールを何もしないモジュールや「品切れ」と表示するモジュールにすり替える。あるいはモジュール内にあるforやwhileの条件式を狂わせたりする。まさにAcme社!
Acme::Module::Authorsプログラムの実行終了時にuseしたモジュールの作者一覧が表示され,感謝を表明する
Acme::Nothingモジュールをuseしても何も起こらなくする
Acme::RemoteINCuseしたモジュールが存在しないときにFTP経由でダウンロード,インストールする
Acme::SpiderDamian Conwayの作ったモジュールをインストールできなくする(彼はクモが嫌い)
Acme::use::strict::with::prideuseしたモジュール内にuse strictとuse warningsを加える

著者プロフィール

まかまか般若波羅蜜(まかまかはんにゃはらみつ)

日本でも数少ないPerlの同人サークル「どんぞこ楽屋」を主催(メンバーは本人しかいない)。年1回,CPANにリリースされている全てのAcmeモジュールを紹介する「Acme大全」を発行,コミックマーケットや各種PM(Perl Mongerの集まり)にて頒布している。YAPC::AsiaでもスピーカーとしてPerlの自作カードゲームやボードゲームなどの発表をしている。Hachioji.pmによく出没。

Twitter:@maka2_donzoko

email:makamaka.donzoko@gmail.com

url:http://www.donzoko.net/gakuya/

コメント

コメントの記入