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:: いじるのはよっぽどの時にしか使えないなーと実感。

カテゴリ

トラックバック(0)

このブログ記事を参照しているブログ一覧: CORE::GLOBAL:: 覚え書き

このブログ記事に対するトラックバックURL: http://www.fs-output.com/rintaro/mt/mt-tb.cgi/24

コメントする

(初めてコメントする場合、承認されるまではコメントが表示されない場合があります。)

このブログ記事について

このページは、Rintaroが2007年8月20日 03:45に書いたブログ記事です。

ひとつ前のブログ記事は「Re: メソッド呼び出しで継承する」です。

次のブログ記事は「クラスメソッドのインポート」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.0rc4