CORE::GLOBAL:: 覚え書き
前のエントリを考えてるときに、CORE::GLOBAL::caller をlocalで定義してやればいいんでないかと:
sub UNIVERSAL::base {
my $class = shift;
local *CORE::GLOBAL::caller = sub(;$) {
my $height = $_[0] || 0;
CORE::caller(1) eq __PACKAGE__ ? $class : CORE::caller($height+1);
};
base->import(@_);
}
こんなコードを書いてみたものの、うまく行かなかった(base.pmのcallerでCORE::GLOBAL::callerが呼び出されない)。
なんでー?と思っていろいろ漁ってたら、perlmonksに答えがありました。 callerが呼ばれるコードがコンパイルされる前にCORE::GLOBAL::callerを定義しておかなければいけないんですね。
ってことはSub::Uplevelなんかも同じなはず。ソース見ると
# We must override *CORE::GLOBAL::caller if it hasn't already been
# overridden or else Perl won't see our local override later.
if ( not defined *CORE::GLOBAL::caller{CODE} ) {
*CORE::GLOBAL::caller = \&_normal_caller;
}
と、一応その対策はされているんだけど、useされるのが遅れたらだめじゃないの? と思って
sub foo { warn join ' - ', caller;}
use Sub::Uplevel;
sub bar { warn join ' - ', caller;}
sub baz {
uplevel 1, \&foo;
uplevel 1, \&bar;
}
#line 123
baz();
こんなコードを実行してみたら、案の定、
Sub::Uplevel - /usr/lib/perl5/site_perl/5.8.8/Sub/Uplevel.pm - 93 at uplevel.pl line 1.
main - uplevel_test.pl - 123 at uplevel.pl line 3.
だそうで。
ということは base.pmがコンパイルされる前に確実にUNIVERSAL::baseがコンパイルされないと実現 不可能。そんなのは無理な相談なので、CORE::GLOBAL::callerの案は却下になったのでした。
やっぱCORE::GLOBAL:: いじるのはよっぽどの時にしか使えないなーと実感。
カテゴリ
Perlトラックバック(0)
このブログ記事を参照しているブログ一覧: CORE::GLOBAL:: 覚え書き
このブログ記事に対するトラックバックURL: http://www.fs-output.com/rintaro/mt/mt-tb.cgi/24

コメントする