tokuhirom's Blog

prototype() をつかった方がいいケースを発見した

Test::More のメソッドをいくつかフックしたいという場合において、is とかは prototype が ($$;$) とついているが、is_deeply には prototype がついていない。このような場合に、どうするか。

    for my $sub (qw/is like isa_ok isnt unlike/) {
        *{"Test::Declare::${sub}"} = sub ($$;$) {
            push @_, $test_block_name if @_ == 2;
            goto \&{"Test::More::${sub}"};
        }
    }

こういうのを処理する際には、

use Scalar::Util ();
for my $sub (qw/is like isa_ok isnt unlike/) {
   my $newsub = sub {
      push @_, $test_block_name if @_ == 2;
      goto \&{"Test::More::${sub}"};
   };
   Scalar::Util::set_prototype($newsub, prototype(\&{"Test::More::${sub}"}));
   *{"Test::Declare::${sub}"} = $newsub;
}

のようにするとよいのではないか。

prototype() などという関数は使い道がなく、手術でとりのぞいてしまっても構わない扁桃腺のような存在だとおもっていたが、実はこんなところに使い道があったのだ。

【追記】
とはいえ、組み込み関数である必要はなく、Scalar::Util のメソッド程度で十分だとおもいます =)