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