てきとうなメモ

本の感想とか技術メモとか

non-capturing parentheses

でも、そうでなければ、どのような時に?:という余分な2文字をわざわざ記述する正当な理由があるのだろうか?

L'eclat des jours(2008-11-26)

(?:...)のメリットはキャプチャしないのでパフォーマンスが上がるという部分がメリットと思っていた.でも測ったことないのでちょっと試してみる.キャプチャする文字列の長さによって違うのではと思うので以下のようなコードで.

use Benchmark qw(:all);
my $size = shift;
my $count = shift;
my $test = 'a' x $size . 'b' x $size;

cmpthese(100000, {
  'capture' => sub { $test =~ /(a+)(b+)/o; },
  'non-capture' => sub { $test =~ /(?:a+)(?:b+)/o;  },
});
$ perl capture.pl 10 1000000
                 Rate     capture non-capture
capture      862069/s          --        -37%
non-capture 1369863/s         59%          --
$ perl capture.pl 100 1000000
                Rate     capture non-capture
capture     694444/s          --        -18%
non-capture 847458/s         22%          --
$ perl capture.pl 1000 1000000
                Rate non-capture     capture
non-capture 255754/s          --         -6%
capture     272480/s          7%          --
$ perl capture.pl 10000 100000
               Rate     capture non-capture
capture     10989/s          --        -64%
non-capture 30303/s        176%          --
$ perl capture.pl 100000 10000
              Rate     capture non-capture
capture     1580/s          --        -50%
non-capture 3165/s        100%          --

効率はよくなるが,思っていたよりもあまり大きな差はないので,それが特に問題になる場合以外は使わなくてもよさそう.

あと,Perlだと以下のような書き方ができるので

($y, $m, $d) = ($str =~ m|(\d{4})(?:/(\d{2})(?:/(\d{2}))?)?|o);

これを,こんなのや

($y, $dummy1, $m, $dummy2, $d) = ($str =~ m|(\d{4})(/(\d{2})(/(\d{2}))?)?|o);

こんなふうに書くのは嫌だなあと

($y, $m, $d) = ($str =~ m|(\d{4})(/(\d{2})(/(\d{2}))?)?|o)[0,2,4];

まあ,上記のようなものは名前付けを一行でやりたいために書いているので,perl5.10.0以降はnamed captureを使えというものなのかもしれない.

全体的にわざわざ書くほどの価値はあるのかというと,価値があるとまで言えるのは一部の場合に限られてくるのかなと思う.この部分,Jeffrey FriedlのMastering Regular Expressionでも突っ込まれていて,「(?:...)って変な表記法だよね.?あるけどoptionalの意味ではないし.私は本当に必要な時にのみ利用している」みたいなことを言っている.

じゃあ,なんで(?:になったのかというと,これまたMastering Regular Expressionに少し説明が書いてあった.それによると,Perl5でこのような新規機能を追加する時に,()[]{}<>などの表現を利用することはできなかった.そこで,Larryが(?を思いついた.(?はそれまでPerl正規表現としてはillegalであったため,自由に意味を与えることができたということらしい.

perldoc perlreにも書いてあった.

A question mark was chosen for this and for the minimal‐matching
construct because 1) question marks are rare in older regular
expressions, and 2) whenever you see one, you should stop and
"question" exactly what is going on. That’s psychology...

2の理由はすごいな.