某社の後輩に下記のブログの件は、普通はどうやって解決するのかと聞かれた(てか、後輩のブログだったようだ、なぜ言わないw)。
http://d.hatena.ne.jp/foosin/20090331/1238509129
僕も以前、悩んだことがあり、Exporterのドキュメントを見たら、まんま書いてたという。export_to_level。
sub import { strict->import; warnings->import; __PACKAGE__->export_to_level(1, @_); }
で、まぁ、おしまい。
Perl のExportの仕組みは、perldoc -f use を見るとわかりやすいんだけど。
BEGIN { require Module; import Module LIST; }
LIST部分が、use Module (...)の、(...)の部分。インポートする関数や、グルーピングの名前とかを取ったりする。
このimportていうメソッドがイクスポートの役割を担っている。で、普通は継承しているExporterの、importが使われる。
そのため、自前でimportを実装すると、Exporterから継承しているimportが呼ばれないので、困ったことになる。
Exporterのimport内で、callerで呼び出し元のpackageを見ているので、->SUPER::importとかしても駄目。
でも、そんなことは想定されていて、Exporterのドキュメントでは、export_to_levelを使えと書いてある。
package A; @ISA = qw(Exporter); @EXPORT_OK = qw ($b); sub import { $A::b = 1; A->export_to_level(1, @_); }
と、知ってたんだけど使ったことなかったんですが、これを書くために使ってみたら、普通にうまく行きました。
って、もっといろんなパターンが下記ですでに紹介されてました。
http://d.hatena.ne.jp/dayflower/20090330/1238399982
ちなみに、あんまり関係ないけど、importを呼びたくない場合は、() を渡します。
これも、perldoc -f useに書いてるけど、
use Module ();
That is exactly equivalent to
BEGIN { require Module }
昔、Mod_perl Developer's Cookbookを読んでて、メモリ節約(余計なimportをしない)のテクニックで紹介されてて知った。
で、本題は、ここのブクマコメント。元某社の後輩が書いているブクマコメント。
http://b.hatena.ne.jp/kamipo/20090401#bookmark-12768808
sub import { strict->import; warnings->import; goto &Exporter::import; }
さっき書いたとおり、Exporterのimportは呼び出し元みてるから駄目じゃないんかと思ったけど、
gotoって、呼び出し元が、呼んだところにならないんですね。へぇ〜。
sub w { print join(" ", caller),"\n" } package Hoge; sub hoge{ goto &main::w }; package Fuga; sub fuga { goto &main::w } package Main; Fuga->fuga; Hoge->hoge;
実行結果は、
Main - 19 Main - 20
知らんかった。だいぶびっくりした。
まぁ、goto使った事は無いけども
# 本題のが短くなってしまった