tsucchi’s diary(元はてなダイアリー)

はてなダイアリー(d.hatena.ne.jp/tsucchi1022)から移行したものです

動的に関数ベースのモジュールを読み込む

タイトルだと何のことやらさっぱりかもしれませんが、やりたいことは、モジュールの 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 設計が間違っているような気もしないでもない。。。