9

プロジェクトのほぼすべてのスクリプトとモジュールで使用されるいくつかのモジュールを作成したいと考えています。これらは、次のように各スクリプトで使用できます。

#!/usr/bin/perl

use Foo::Bar;
use Foo::Baz;
use Foo::Qux;
use Foo::Quux;

# Potentially many more.

これらすべてのuseステートメントを新しいモジュールに移動して、スクリプトとモジュールのそれぞれでFoo::Corgeのみ移動することは可能ですか?use Foo::Corge

4

6 に答える 6

7

このようなものが動作するはずです:

http://mail.pm.org/pipermail/chicago-talk/2008-March/004829.html

基本的に、多くのモジュールを含むパッケージを作成します。

package Lots::Of::Modules;
use strict; # strictly optional, really

# These are the modules we want everywhere we say "use Lots::Of::Modules".
# Any exports are re-imported to the module that says "use Lots::Of::Modules"
use Carp qw/confess cluck/;
use Path::Class qw/file dir/;
...

sub import {
    my $caller = caller;
    my $class  = shift;

    no strict;
    *{ $caller. '::'. $_ } = \*{ $class. '::'. $_ }
       for grep { !/(?:BEGIN|import)/ } keys %{ $class. '::' };
}

次に、他の場所で Sets::Of::Modules を使用します。

use Lots::Of::Modules;
confess 'OH NOES';
于 2009-01-13T03:06:44.000 に答える
3

はい。

Foo/Corge.pm で

use Foo::Bar;
use Foo::Baz;
use Foo::Qux;
use Foo::Quux;

1;   # Be successful

あとは、サブディレクトリを含むディレクトリをFooライブラリ パスに追加するだけです ( @INC)。または、他のモジュールを作成Foo.pmして使用します。それらは のFoo横のサブディレクトリにありFoo.pmます。

考えてみれば、他のモジュールを使用するすべての複雑な Perl モジュールは、常にこれを行っています。それらは必ずしも同じ最上位パッケージ (Fooこの例では) にあるとは限りませんが、必要に応じて使用されます。

Carp や Path::Class を使用して告白することもできますが (jrockway が示唆するように)、それは私が座っている場所からはやり過ぎのように思えます。

于 2009-01-13T04:21:14.847 に答える
0

別のオプションは、Foo::Corge が関心のあるアイテムを通常どおり再エクスポートすることです。

package Foo::Corge;

use base 'Exporter';
BEGIN {
  our @EXPORT_OK = qw( bar baz qux quux );

  use Foo::Bar qw( bar );
  use Foo::Baz qw( baz );
  use Foo::Qux qw( qux );
  use Foo::Quux qw( quux );
}
1;

('use' ステートメントはおそらく の外に出ることができますBEGINが、私がチェックしたコードでは、これが私が思ったように機能することを確認した場所です。そのコードは実際にevalは suseであるため、そうなる理由があります。あなたの場合には当てはまらBEGINない可能性があります。)

于 2009-02-03T12:12:14.173 に答える
0

@EXPORT_OK の代わりに @EXPORT を使用すると、より簡単になります

ライブラリは次のとおりです。

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(test);

sub test {
    print "this is a test";
}

1;

これを使って:

#!/usr/bin/perl
use strict;
use warnings;
use mycommon;

common::test()
于 2013-11-14T21:44:31.737 に答える
0

[編集: 私の以前のソリューションにuse Lots::Of::Modules;は微妙なバグがありました -- 下部を参照してください。この修正により、少し見苦しくなりますが、それでも機能します。]

[編集 #2:BEGIN { ... }定義された関数がコンパイル時に確実に使用できるように、コードの周りに追加されました。これを指摘してくれた jrockway に感謝します。]

次のコードは、jrockway のコードが行うこととまったく同じことを行いますが、より単純で明確です。

Sets/Of/Modules.inc:

use Carp qw/confess cluck/;
use Path::Class qw/file dir/;

0;   # Flag an error if called with "use" or "require" instead of "do"

これら 4 つの関数をインポートするには:

BEGIN { defined( do 'Lots/Of/Modules.inc' ) or die; }

package Lots::Of::Modules;このファイルの先頭にステートメントがないため、useステートメントは呼び出し元のパッケージにエクスポートされます。

またはdoの代わりに使用する必要があります。後者はファイルを 1 回しかロードしないためです (が複数回呼び出されると失敗します。たとえば、メイン プログラムによって別々のモジュールで呼び出されます)。よりプリミティブなは、引数で指定されたファイルが で見つからない場合でも例外をスローしません。したがって、 で結果をチェックする必要があります。userequireuse Lots::Of::Modules;usedo@INCdefined

于 2009-01-14T05:00:58.013 に答える