use Exporterする時のメモ
Minilla便利だわー!って思って、モジュールを作ってみたのですが、
Exporterがよく分からなかったのでメモ。
こんな感じで、スクリプトとモジュールを配置。
.
├── aaa.pl
└── lib
└── Foo.pm
“Foo.pm”はこんな感じ。
ちなみに、(caller(0))[3];は、現在の関数名を返してくれます。
詳しくは、こちら(http://perldoc.jp/func/caller)を参照してください。
package Foo;
use strict;
use warnings;
use base qw(Exporter);
our @EXPORT = qw(foo);
our @EXPORT_OK = qw(foo bar);
our %EXPORT_TAGS = (
all => [ @EXPORT, @EXPORT_OK ],
hoge => [ qw(hoge) ]
);
sub foo { (caller(0))[3]; }
sub bar { (caller(0))[3]; }
sub hoge { (caller(0))[3]; }
sub fuga { (caller(0))[3]; }
1;
という訳で、”aaa.pl”を編集しながら実行してみます。
use v5.12; use warnings; use Foo; say 'Foo::foo() => ', Foo::foo(); say 'foo() => ', foo();
$ perl -Ilib aaa.pl
Foo::foo() => Foo::foo
foo() => Foo::foo
これに関しては、だいたい予想通りですかね。
our @EXPORT = qw(foo);があるので、
Foo::foo()はもちろんのこと、foo()だけでも動作します。
次に、以下のように変更してみます。
use v5.12; use warnings; use Foo qw(bar); say 'Foo::foo() => ', Foo::foo(); say 'foo() => ', foo();
$ perl -Ilib aaa.pl
Foo::foo() => Foo::foo
Undefined subroutine &main::foo called at aaa.pl line 7.
この場合、use Foo qw(bar);でインポートする関数を指定しているので、
デフォルトの動作が行われずに失敗してしまいました。
ここでデフォルトの動作???ってなると思いますが、
実は、use Foo;とuse Foo qw(:DEFAULT);は一緒なのです。
では、試してみましょう。
use v5.12; use warnings; use Foo qw(:DEFAULT); say 'Foo::foo() => ', Foo::foo(); say 'foo() => ', foo();
$ perl -Ilib aaa.pl
Foo::foo() => Foo::foo
foo() => Foo::foo
ちなみに:DEFAULTは、こんな感じで使われることがあるそうです。
use v5.12; use warnings; use Foo qw(:DEFAULT bar); say 'Foo::foo() => ', Foo::foo(); say 'foo() => ', foo(); say 'bar() => ', bar();
$ perl -Ilib aaa.pl
Foo::foo() => Foo::foo
foo() => Foo::foo
bar() => Foo::bar
fooとbarに関しては、
our @EXPORT_OK = qw(foo bar);によってインポートが許可されていますが、
他はどうでしょう?
use v5.12; use warnings; use Foo qw(hoge); say 'Foo::hoge() => ', Foo::hoge(); say 'hoge() => ', hoge();
$ perl -Ilib aaa.pl
"hoge" is not exported by the Foo module
Can't continue after import errors at aaa.pl line 4.
BEGIN failed--compilation aborted at aaa.pl line 4.
hoge()は、@EXPORT_OKに含まれていないためダメなようです。
ですが、これなら動きます。
use v5.12; use warnings; use Foo; say 'Foo::hoge() => ', Foo::hoge(); #say 'hoge() => ', hoge();
$ perl -Ilib aaa.pl
Foo::hoge() => Foo::hoge
つまり、@EXPORT_OKを定義(宣言?)することで、
使って欲しい関数と、使って欲しくない関数を伝えることはできます。
次に、先ほどの:DEFAULTのように、
引数を指定して関数をインポートしてみたいと思います。
use v5.12; use warnings; use Foo qw(:all); say 'foo() => ', foo(); say 'bar() => ', bar();
$ perl -Ilib aaa.pl
foo() => Foo::foo
bar() => Foo::bar
%EXPORT_TAGSに、all => [ @EXPORT, @EXPORT_OK ]があるので、
:allを指定すると、fooとbarがインポートできました。
@EXPORTと@EXPORT_OKの両方にfooが存在してますが、
これは問題ないそうです。
では、hoge => [ qw(hoge) ]の方はどうでしょう?
use v5.12; use warnings; use Foo qw(:hoge); say 'Foo::hoge() => ', Foo::hoge(); say 'hoge() => ', hoge();
$ perl -Ilib aaa.pl
"hoge" is not exported by the Foo module
Can't continue after import errors at aaa.pl line 4.
BEGIN failed--compilation aborted at aaa.pl line 4.
残念ながら、@EXPORT、または@EXPORT_OKに含まれていないと、
hoge => [ qw(hoge) ]でエクスポートできないようです。
ちなみに、:DEFAULTや:allはタグと呼ばれており、
このタグに関連付けられた関数群のことをインポートリストと呼ぶそうです。(*1)
最後に、モジュールから一つも関数をインポートしたくない場合。
use v5.12; use warnings; use Foo (); say 'Foo::foo() => ', Foo::foo(); say 'foo() => ', foo();
$ perl -Ilib aaa.pl
Foo::foo() => Foo::foo
Undefined subroutine &main::foo called at aaa.pl line 7.
今回のネタ元はこちら。
という訳で、今さら聞けないこともカジュアルに聞けちゃう勉強会、
Hokkaido.pm Casualの次の予定は6/19となっております。
詳しくは、こちら(Hokkaido Perl Mongers)をご覧下さい。
おしまい。
(*1) 続・初めてのPerl 改訂版(Amazon)より。
Leave a Comment