+{ } ネタでハマる

HTML::Templateのループに食わせるべく。

my $tmpl = HTML::Template->new(filename => 'hoge');

$tmpl->param(
  list => [
    map {
      my $id = $_;
      {
        id   => $id,
        title  => "title$id",
      };
    } (1..3)
  ]
);

なんてコードを書いたら、ローカルのActivePerl 5.8.6では期待した動作をするのに、検証用の環境に入っていたperl 5.8でエラーになって大ハマリ。さんざん関係ないところで悩んだ末に検証環境でparamの中身をDumperしたら

$VAR1 = 'list';
$VAR2 = [
          'id',
          1,
          'title',
          'title1',
          'id',
          2,
          'title',
          'title2',
          'id',
          3,
          'title',
          'title3',
        ];

のような出力が得られたのでようやく事態を認識して、

my @list;
foreach my $id (1..3) {
  push @list, {
    id    => $id,
    title => "title$id",
  };
]
$tmpl->param( list => \@list );

と書き換えてひとまずはお茶を濁したのですが、敗北感がぬぐえずさらに調べてみたところ、

$tmpl->param(
  list => [
    map {
      {
        id    => $_,
        title => "title$_",
      }
    } (1..3)
  ]
);

これなら5.005、5.6.1、5,8.6でそれぞれ問題なし。

$tmpl->param(
  list => [
    map {
      my $id = $_;
      {
        id    => $id,
        title => "title$id",
      }
    } (1..3)
  ]
);

もともとのこれは5.005、5.6.1でハマリ。5.8でもNG。そこから5.8.6に至るどこかでOKになった模様。

$tmpl->param(
  list => [
    map {
      my $id = $_;
      my $href = {
        id    => $id,
        title => "title$id",
      }
    } (1..3)
  ]
);

これは5.005以降でOK。

で、ここまで書いて、はたと気がついた。

$tmpl->param(
  list => [
    map {
      my $id = $_;
      +{
        id    => $id,
        title => "title$id",
      }
    } (1..3)
  ]
);

もちろん5.005以降でOK。

いつぞやのLLDNで大笑いしたアレ、こんなところで使うものだったのですね!(違