だるろぐ

だるいぶろぐです

m//の戻り値

久々に。

use strict;
use warnings;
use Data::Dumper;sub p {warn Dumper [@_];my @c = caller;print STDERR "  at $c[1]:$c[2]\n\n"}

my $s = "hoge";
my ($d,$r) = (0,0);
($d,$r) = (($s =~ /sss/),($s =~ /hoge/));
p $d, $r; # case 1

($d,$r) = (($s =~ /hoge/),($s =~ /aaa/));
p $d, $r; # case 2

これを実行したときの結果が、予想と違って悩んだ。

  • 俺の予想
    • case 1
      • ($d, $r) は (undef, 1)
    • case 2
      • ($d, $r) は (1, undef)
  • 現実
% perl h.pl
$VAR1 = [
          1,
          undef
        ];
  at h.pl:8

$VAR1 = [
          1,
          undef
        ];
  at h.pl:11


相変わらず現実は厳しくて安心。
一通り悩んだ後、いつもどおり柔道家にhelp。成長が見えない。先に言っておきます、毎度ありがとうございます。

さくっと結論

% perldoc perlop

If the "/g" option is not used, "m//" in list context returns a list consisting of the subexpressions matched by the
parentheses in the pattern, i.e., ($1, $2, $3...).  (Note that here $1 etc. are also set, and that this differs from
Perl 4’s behavior.)  When there are no parentheses in the pattern, the return value is the list "(1)" for success.)
With or without parentheses, an empty list is returned upon failure.

訳:http://perldoc.jp/docs/perl/5.8.8/perlop.pod

/gオプションが使われなかった場合、リストコンテキストでのm//はパターンの中の括弧で括られた部分列にマッチしたもので構成されるリストを返します。これは、($1, $2, $3, ...) ということです。 (この場合、$1 なども設定されます。この点で Perl 4 の動作と違っています。) パターンに括弧がない場合は、返り値は成功時はリスト (1) です。括弧のあるなしに関わらず、失敗時は空リストを返します。


要は。m//は、マッチしたら真を返すが、マッチしなかったら、偽を返すのではなく、空リストを返す。のが原因。
空リストとは () のこと。どんな動作になるかというと。

my ($h, $d) = ((), 1); # これは my ($h, $d) = (1); に等しい
p $h, $d;

これが

$VAR1 = [
          1,
          undef
        ];

こうなる。左辺をリストで受けた場合、右辺の先頭に空リストがあったら、次の要素が左に詰められる。
で、$hには1が入り、$dは何も受けられないからundefとなる、と。


仕様も読まずに、「m//はマッチに失敗したら偽を返す」と思い込んでたのが原因。
perldoc読めって話でした。