動的に関数ベースのモジュールを読み込む
タイトルだと何のことやらさっぱりかもしれませんが、やりたいことは、モジュールの use のオプションを指定した際に、別のモジュール(関数ベースのインターフェース)を読み込む。そのときに、main パッケージで関数ベースがインポートされるようにしたい、ということ。
サンプルを作るとこんな感じ。
- 呼び出したい関数ベースのモジュール(dynamic.pm)
#!/usr/bin/perl use strict; use warnings; package dynamic; use base qw(Exporter); our @EXPORT = qw( do_something ); sub do_something{ print "do_something\n"; } 1;
do_something がインポートしたいやつ。
- main から呼ばれる別のモジュール(X.pm)
#!/usr/bin/perl use strict; use warnings; package X; sub new { bless {}, shift; } sub import { my ($package, @arg) = @_; dynamically_load_do_something() if ( $arg[0] eq 'do_something' ); } sub dynamically_load_do_something { #この関数を使って dynamic.pm をいい感じに呼び出したいのだが、どうしたものか。。。 } 1;
- main(名前は何でも良いけど、例によって a.pl)
#!/usr/bin/perl use strict; use warnings; use X qw(do_something); #do_something オプションを指定すると。。。 my $x = X->new(); do_something(); # dynamic.pm の do_something がここにインポートされる
で、X.pm の dynamically_load_do_something をどうしようか、迷った次第。
試行錯誤したところ、こんな感じになったのですが、コレであってるのかなぁ???
sub dynamically_load_do_something { require "dynamic.pm"; { package main; dynamic->import(); } }
「package main」がうさんくさい感じでちょっと嫌です。caller() とか使えばいいのかな?それとも、dynamic.pm 側が Exporter じゃなくて自前で実装しないとダメなのか?
そもそも、もともとやりたいことの API 設計が間違っているような気もしないでもない。。。