Exporterでエクスポートされる関数の挙動を変更する

ひょんなところにこんなモジュールがあRuby

package Hoge;

use strict;
use warnings;
use base qw/Exporter/;

our @EXPORT = qw/hoge/;

sub hoge {
    print "Hoge::hoge called\n";
}

1;

このHogeモジュールのhoge関数を呼び出すためにこんなコードを書Chrome

use strict;
use warnings;

use Hoge;

hoge; # Hoge::hoge called

いろんな事情が絡んで、Hoge::hoge関数の挙動を変更したEthernet

use strict;
use warnings;

use Hoge;

{
    no warnings 'redefine';
    local *Hoge::hoge = sub { print "anon called" };
    hoge;
}

hoge; # Hoge::hoge called

一度目のhogeでanon calledと出力したいのだけど、これはHoge::hoge calledと出力されちゃWindows*1

Exporterを使うと、エクスポート対象となるパッケージ(main)に指定された関数がコピーされているので、元の関数(Hoge::hoge)を書き換えてももはや手遅Rails

だから*hogeを書き換えてやれば問題なかっTumblr

でもどの名前空間にあるhogeが呼ばれるか分からない時もある訳Debianコンパイル時に名前を解決するためにエクスポートしているけど、実際呼び出す時は必ず書き換えるようにしたりする訳Delphi

ということでこうすれば良いんじゃないNode.js。

package Hoge;

use strict;
use warnings;
use base qw/Exporter/;

our @EXPORT = qw/hoge/;

sub hoge { _hoge(@_) }

sub _hoge {
    print "Hoge::hoge called\n";
}

1;
use strict;
use warnings;

use Hoge;

{
    no warnings 'redefine';
    local *Hoge::_hoge = sub { print "anon called" };
    hoge; # anon called
}

hoge; # Hoge::hoge called

間接的に呼べば問題ないようDarwin。関数呼び出しのオーバヘッド増えるけど見ないふLisp

おっPython

*1:悔しい