Perldocの話B!

lestrratこと牧です。AnyEventの話を書こうと思ったけど、それは本を書くくらいの厚さになりそうなのでやめました。「リアルタイムWebのためのPerl」って本書きたいので、編集さん誰か連絡ください。

ああ、advent calendarでした。

カジュアルトラックなので、カジュアルに使うために有用なテクニックってなんだったのかと考えたのですが、やっぱりperldocじゃないかな、と。僕がperlを2000年頃に使い始めてまず感動したのはドキュメントを漁りにネットに繋げなくてもよいということでした(当時はJavaを大学で使っていたので、ものすごく頻繁にjava.sun.comのjavadocページを見ていた)。

コマンドラインで

% perldoc CGI

ってするだけでCGI.pmのドキュメントが読めるんですよ?感動じゃないですか。manはそのままコンソールで読めるのに、javadocはなんでそれができないのかいつも不思議でした。今はもうそういうツールがあるのかもしれませんが、もうJava書かないのでどうでもいいです。

で、このperldoc モジュール名perldoc -f 関数名という使い方は有名ですが、例えば$]って何が格納されてるの?とかのPerl本体の説明については意外とみんなどこにドキュメントがあるのか知らないので、その辺りをちらちらと書きたいと思います。

まず真っ先に、もし「どんなperldocあったか忘れちゃったなぁ・・・」以下のようにしてください。"For ease of access, the Perl manual has been split up into several sections(簡単にアクセスできるようにPerlマニュアルはいくつかのセクションに分けられています)"という文言の後にずらずらとperldoc経由で読めるマニュアル一式がでてきます。

% perldoc perl

ちなみに僕が使っているperl 5.8.8では約190個のエントリがならんでいました。

このうち、自分が比較的頻繁に読むセクションを紹介してみます:

perlvar

perlvarはいわゆる巷で言われる「Perlの訳の分からない変数」がリストされています。変数は「variable」というのでperlvarです。下唇を噛んで発音して覚えて下さいね

このマニュアルを使うときは前半の説明とかどうでもいいので、お使いのビューアーの検索機能で探したい変数の名前を一気に探すのが吉です。

あと、このマニュアルにはuse Englishというものと、use Englishが提供する特殊変数の代替版がリストされています(例:$/ → $INPUT_RECORD_SEPARATOR)が、これはさっくり無視しましょう。use Englishはメモリも食う割にはあんまりメリットがないです。経験者は語ります。

ともあれ、特殊変数なんて別に暗記する必要もないので忘れる度にこのマニュアルを見に行ってます。僕が一案よく使う特殊変数は $]と$/ですね。

perlre

これはいわゆる正規表現のマニュアルです。これまた文法をよく忘れるのでよく使います。perlvarと同じくビューアーの検索を使うのが吉ですが、何せ記号だらけなのでvimなどの正規表現を理解する検索システムではエスケープしなくてはいけないので余計に検索しにくいです。

個人的には"Extended Patterns"の項を一番よく使ってます。特に忘れがちなのが"zero-width look-ahead"系と"zero-width look-behind"系です。

$string =~ /(foo(?=bar))/; # fooの後にbarが存在したら、"foo"をマッチ
$string =~ /(foo(?!bar))/; # fooの後にbarが存在しなかったら、"foo"をマッチ
$string =~ /((?<=bar)foo)/; # fooの前にbarが存在したら、"foo"をマッチ
$string =~ /((?<!bar)foo)/; # fooの前にbarが存在しなかったら、"foo"をマッチ
(?!)

はよく使うので覚えているのですが、それ以外はどうしても覚えられない。ちなみにここで検索する場合は上記のように"look-ahead"とか、そういうキーワードをちょっと覚えていると検索しやすいです。

その他正規表現の仕組みついて色々説明してくれているので、Jeffrey Friedl氏の名著「詳説 正規表現」にお金を出したくない人は読んでおくといいかもしれません。

perlopentut

Perlのopen()関数は色々な使い道があるので結構忘れがちです。perlopentut(これ以後もそうですが、チュートリアル→tutorial→tutと覚えてくださいね)ではこのopenの様々な使い方を教えてくれます。

この章は特に検索に使うというより、とにかくopen() の使い方を教えてくれるので、暇な時にでも熟読してみるといいんじゃないでしょうか。open() のリファレンスとしては perldoc -f openのほうがいいかもしれません。

perlpacktut

こちらはPerlのpack() 関数を教えてくれるチュートリアルです。バイナリアンじゃない僕はここに書いてあることがぼんやりとしかわかってませんが、とりあえずこれを読みながらmemcachedのバイナリプロトコルを実装したりしてました。perldoc -f packも、packのテンプレート種別が一気に表示されるので便利です。

perlipc

IPCとはInter-Process Communicationの事で、要はプロセス間通信です。僕はfork()を使ったコードをある一定の周期で書くことが多いのですが、そのたびに子プロセスの回収の仕方を忘れるので毎回ここで見て思い出します。どうしてもwaitpidとかが思い出せないのです。で、いつもこんなコードを書きます:

use strict;
use POSIX qw(WNOHANG);

my %children;
my $to_fork = 10;

local $SIG{CHLD} = sub {
    while ( (my $pid = waitpid(-1, WNOHANG()) > 0 ) ) {
        delete $children{$pid};
    }
};

for my $i (1..10) {
    my $pid = fork();
    if (! defined $pid) {
        die "Failed to fork";
    }

    if ($pid) { # parent
        $children{ $pid }++;
    } else {
        # child
        local %SIG;
        ....
        exit;
    }
}

# なにかしながら%childrenが空になるのを待つ

perlxs, perlapi, perlapio, perlguts, perlclib

PerlのCバインディングであるXSを書くときはこの辺りは必須です。

perlxsはXSの基本、perlclibはCレイヤーでPerlが提供するユーティリティ関数(メモリ確保とか、文字列比較とか)のリスト、perlapiはPerlの関数・マクロ群、perlapioはI/O関連のAPI、perlgutsは内部構造の説明等が載ってます。

正直XSのイントロとしては無理があるので、拙著「モダンPerl入門」を推したいところですが、個人的にはこれらのマニュアルと、Tim Bunce氏のMemcached::libmemcachedのソースコードが大変ためになりました。

以上個人的によく使っているマニュアル群でした。これ以外にも結構たくさんありますので是非どうぞ。ちなみに有志で日本語翻訳を行ってくれているperldocjpプロジェクトがいままで訳してきたそれらのマニュアルはこちらから入手可能です:https://perldoc.jp/docs/perl/。 5.10.x系まで揃ってるので英語が難しいという方はこちらもあわせてどうぞ。