Let's use the /x modifier!

Perl ベストプラクティス』はクセの強い本ではあるが、私のプログラミングスタイルが受けた影響は少なくない。なかでも、PBPによってPerl正規表現の/x修飾子のすばらしさを知ったことは大きい。これはPBP以前は使おうと思ったことがなかったが、今となってはこれなしに複雑な正規表現を書こうとは思わない。
/x修飾子は、正規表現中の空白を無視し、コメントを入れられるようにするための修飾子だ*1
以下の正規表現は、Text::Xslateから抜粋したものだ。
In Text/Xslate/Util.pm:

our $NUMBER  = qr/ (?:
        (?: [0-9][0-9_]* (?: \. [0-9_]+)? \b) # decimal
        |
        (?: 0 (?:
            (?: [0-7_]+ )        # octal
            |
            (?: x [0-9a-fA-F_]+) # hex
            |
            (?: b [01_]+ )       # binary
        )?)
    )/xms;

これはXslateのテンプレートでにおける数値リテラルにマッチする*2。これを/xなしで書くと以下のようになる。

our $NUMBER = qr/(?:(?:[0-9][0-9_]*(?:\.[0-9_]+)?\b)|(?:0(?:(?:[0-7_]+)|(?:x[0-9a-fA-F_]+)|(?:b[01_]+)?))/ms;

恐ろしい。これでは何をやっているのかさっぱりわからず、「write only」のそしりは免れられない。PBPが主張するように、正規表現は一つのプログラミング言語なのだ。インデントも空白もコメントもないプログラムなど保守できないと思うならば、それは正規表現にも当てはまる。インデントも空白もコメントもない正規表現もまた保守できないのだ。だから、ある正規表現を公開するなら、あるいは継続的にメンテナンスをするつもりなら、あなたもぜひ/x修飾子をつかってほしい。たしかにqr/ /が' 'にマッチすることに慣れていると最初は違和感がある。しかし、慣れるともう以前の「インデントなし」の世界には戻れなくなるだろう!
[追記]
[twitter:@tokuhirom]から指摘されたので追記。
/xを使わない場合には、以下のように正規表現を分けるのが普通だ。

my $decimal  = qr/(?:[0-9][0-9_]*(?:\.[0-9_]+)?\b)/;
my $octal    = qr/(?:0[0-7_]+)/;
my $hex      = qr/(?:0x[0-9a-fA-F_]+)/;
my $binary   = qr/(?:0b[01_]+)/;
our $NUMBER  = qr/(?:$decimal|$octal|$hex|$binary)/;

これならば少なくとも保守はできる。しかしそれでも私には詰まりすぎているように思う。プログラムの他の部分でやっているのと同じように、見やすくするためのスペースは置けたほうがよい。

*1:なお、私は/xは必ず/mおよび/sと同時に使うため、以下の例では/xmsと書く。これもPBPの提唱するプラクティスで、複雑な正規表現の仕様を単純化するためのものだ。詳細はPBPないしperldocを参照のこと。

*2:したがって、必ずしも汎用的に使えるとは限らない。蛇足だが、先頭に[+-]がないのは、それらが単項演算子だからである。