4

私はPerlモジュールを作成する経験がまったくないので、ここから離れていたら申し訳ありません。

いくつかのモジュールを作成しているとしましょう:

foo::bar
foo::bar::a
foo::bar::b

それらが何と呼ばれているのかわからないので、a.pm および b.pm モジュールを「サブモジュール」と呼んでいます。これらは bar.pm モジュールに関連しているためです。ただし、多少独立している可能性もあります。

したがって、私の Perl スクリプトの 1 つは foo::bar::a を使用でき、別のスクリプトは foo::bar::b を使用でき、「a」と「b」の両方の関数を使用する必要がある別のスクリプトがあるかもしれません。これを言う代わりに:

use foo::bar;
use foo::bar::a qw(one two);
use foo::bar::b;

私はこのようなことをしたい:

use foo::bar qw(:a :b);

私の考えでは、これにより、私のスクリプトは bar.pm、a.pm、および b.pm のすべてにアクセスできるようになります。

私はこのようなことをテストしましたが、明らかに間違っていました。

このようなことは可能ですか?bar.pm に a.pm と b.pm を使用させ、呼び出しを「サブモジュール」に渡す「ラッパー」関数を持たせることができると思いますが、もっと簡単な方法があるようです。

4

6 に答える 6

5

それを行う例については、私のTest::Dataモジュールを見てください。あなたはそれを実現することができますが、私はその結果をそれほど気に入ったことはありません. 代わりに、プラグインまたはミックスインのアプローチを検討することをお勧めします。これに役立つCPANのモジュールがいくつかあります。

importTest::Data 用に書いたカスタムは次のとおりです。

サブインポート
    {
    私の $self = シフト;
    私の $caller = 発信者;

    foreach 私の $package ( @_ )
        {
        my $full_package = "Test::Data::$package";
        eval "require $full_package; 1";
        もし($@)
            {
            carp "Test::Data::$package: $@ を要求できませんでした";
            }

        $full_package->export($caller);
        }

    }
于 2009-02-12T17:55:39.253 に答える
2

はい、できます。おそらく、受信引数を希望どおりに解釈するカスタムの「サブインポート」を foo::bar に記述する必要があります。

おそらくあなたは現在 Exporter を使用していますが、あなたの構文がサポートされていないことが問題です。Exporter が実装するモジュール構文については、特に特別なことは何もないことがわかります。それは単なる一般的な慣習です。ただし、どのようにしたいかについての洞察を得るために、それがどのようにビジネスを行っているかを調べたいと思うでしょう.

于 2009-02-12T17:37:19.640 に答える
1

モジュールが何と呼ばれているのかわからない場合、なぜそれを含めているのですか? 含める必要はありません。それを必要とする (呼び出し元の) モジュールにのみモジュールを含め、それ以外の場所には含めません。

つまり、それを使用している場合は、それを「使用」します。使わないなら「使わない」。

于 2009-02-12T19:03:35.547 に答える
0

はい。ただし、独自のインポート サブを装備する必要があります。

use strict;
use warnings;

package ab;
use base qw<Exporter>;
our @EXPORT_OK;
our %EXPORT_TAGS;
BEGIN { 
    @EXPORT_OK   = qw<>;
    %EXPORT_TAGS = ( a => 1, b => 1, all => \@EXPORT_OK );
}

sub setup_part { 
    #use Smart::Comments;
    my $code = shift;
    my $mini_path = "foo/bar/$code.pm";
    return if exists $INC{$mini_path};
    require $mini_path; 
    my $arr_ref 
        = do { no strict 'refs';
            \@{Symbol::qualify( 'EXPORT_OK', $code )};
        };
    $code->import( @$arr_ref );
    push @EXPORT_OK, @$arr_ref;
    $EXPORT_TAGS{$code} = [ @$arr_ref ];
    return;
}

sub import { 
    my ( $package_name, @imports ) = @_;
    my %import_hash = map { $_ => 1 } @imports;
    if ( exists $import_hash{':all'} ) { 
        @import_hash{qw<:a :b>} = ( 1, 1 );
    }
    foreach my $import ( grep { exists $import_hash{$_} } qw<:a :b> ) { 
        setup_part( substr( $import, 1 ));
    }
    goto &{Exporter->can( 'import' )};
}

1;
于 2009-02-12T18:18:24.377 に答える
0

最近のものに似た解決策を探しました。私は知っています - あまりにも古いスレッド - しかし、ブライアン・ド・フォイによる答え ( 2009 年 2 月 12 日 17:55 )にコメントしたいのですが、悲しいことに、これを達成するのに十分な評判がありません。そのため、コメントを新しい応答として追加します。

彼の答えは、最近の問題と同様の問題を解決するのに役立ちました。ただし、 と一緒に使用する場合は、いくつかの変更が必要use libです。

のようなモジュールがたくさんありますA::B::*。これらは、一般的なモジュールによってスクリプトにロードする必要がありますA::B。これらのモジュールはすべて、読み込みスクリプトと同じディレクトリの下のファイル内にあります。brian d foyによって提案されたメカニズムを使用すると、多くのサブルーチン再定義エラーを取得できます。それらすべてを回避するために、より良い解決策を見つけたと思いますno warnings 'redefine'. use libこれで、no warnings 'redefine'またはshift @INC, ...メイン スクリプトで自由に使用できるようになりました。

    サブインポート {
        @TAGS = ( @_ );
        私の $me = シフト @TAGS;

        ( 私の $pm = $me ) =~ s|::|/|g;
        $pm .= ".pm";

        ( $dir = $INC{$pm} ) =~ s/\.pm$//;
        foreach (グロブ "$dir/*.pm") {
            /(\w+)\.pm$/;
            私の $module = "${me}::$1";

            eval "use $module qw(:all)"; # エクスポートリストの項目は自由に使用できます
            die "$me: $module を $_ からロード中にエラーが発生しました: $@\n" if $@;
        }

        # 各 A::B::*::EXPORT_OK から @EXPORT_OK と %EXPORT_TAGS を手動で入力します
        # ...

        goto &{ Exporter->can( "import" ) };
    }

于 2014-04-09T06:42:44.567 に答える
0

Class::MixinFactoryも見てみてください

于 2009-02-12T17:52:18.620 に答える