0

私は、本当に必要な場合を除いて、パッケージを実際に使用することなく、プログラムで.pmファイルを意地悪に使用してきました。本質的に、私は.pmに共通のルーチンを持っているだけで、使用するとメインの一部になります(.pmにはパッケージやエクスポーターなどはありません...ルーチンの束だけです)。

しかし、先日、何が起こったのか、そしてその理由はわかっていると思う状況に遭遇しましたが、ここの専門家からベストプラクティスとその解決方法についての指導を受けたいと思っていました。本質的に、パッケージは常に使用する必要がありますか?一般的なルーチンをメイン(または親モジュール/パッケージ)に吸収させたい場合は、ファイルを「実行」する必要がありますか?Exporterは本当にこれらすべてを処理する方法ですか?

これが私が遭遇したもののサンプルコードです(数千行なので元のコードは投稿しません...これは問題の本質です)。

Pgm1.pl:

use PM1;
use PM2;
print "main\n";
&pm2sub1;
&pm1sub1;

PM1.pm:

package PM1;
require Exporter;
@ISA=qw(Exporter);
@EXPORT=qw(pm1sub1);
use Data::Dump 'dump';
use PM2;
&pm2sub1;
sub pm1sub1 {
    print "pm1sub1 from caller ",dump(caller()),"\n";
    &pm2sub1;
}
1;

PM2.pm:

use Data::Dump 'dump';
sub pm2sub1 {
    print "pm2sub1 from caller ",dump(caller()),"\n";
}
1;

本質的に、私はしばらくの間、その&pm2sub1サブルーチンでPM2.pmを使用していました。次に、ある時点でPM1.pmを作成しましたが、PM2.pmのルーチンも必要でした。ただし、このようにすることで、PM2.pmのモジュールがPM2.pmのパッケージに吸収され、PM2.pmがすでに使用されていたため、Pgm1.plは同じことを実行できませんでした。

このコードは

Undefined subroutine &main::pm2sub1 called at E:\Scripts\PackageFun\Pgm1.pl line 4.
pm2sub1 from caller ("PM1", "PM1.pm", 7)
main

ただし、Pgm1.plでこのようにuseステートメントを交換すると

use PM2;
use PM1;
print "main\n";
&pm2sub1;
&pm1sub1;

... perlは、PM2.pmのモジュールをメインに許可しますが、PM1.pmのパッケージには許可しません。

Undefined subroutine &PM1::pm2sub1 called at PM1.pm line 7.
Compilation failed in require at E:\Scripts\PackageFun\Pgm1.pl line 2.
BEGIN failed--compilation aborted at E:\Scripts\PackageFun\Pgm1.pl line 2.

ですから、すべてのモジュールでパッケージとエクスポーターについて宗教的になることで、これを修正できると思います。問題は、PM2.pmがすでに他の多くのプログラムで使用されているため、何も壊れていないことを確認するための回帰テストが大量に行われることです。

アイデア?

4

3 に答える 3

4

ライブラリファイルとモジュールの違いは何ですか?に対する私の答えを参照してください。。

モジュール(通常は、を含むファイル)にのみ使用しますrequire(したがって)。「ライブラリ」(通常、のないファイル)には、を使用します。usepackage.pmpackage.pldo

さらに良いことに、モジュールのみを使用してください!

于 2012-07-03T18:13:13.697 に答える
3

use同じファイルを複数回ロードすることはありません。ただし、ターゲットパッケージのimportサブを毎回呼び出します。PM2を適切なパッケージとしてフォーマットする必要があります。そうすれば、PM2の関数をuse見つけてimport、そこからリクエスターの名前空間にエクスポートできます。

(または、名前を完全に修飾することで、インポート関数を適切なパッケージに忍び込ませることができますが、そうしないでください。)

于 2012-07-03T18:17:34.387 に答える
0

このようにコードを配置するのに問題が発生しているだけです。各モジュールにパッケージ名(名前空間)を付けてから、その関数への呼び出しを完全に修飾します(例:packagePM2::sub1()で呼び出す) 。すでにパッケージ名が付いた関数に名前を付けています(); 正しい方法でそれを行うには2つの余分な文字()が必要であり、Exporterを気にする必要もありません。sub1PM2pm2sub1::

于 2012-07-03T21:39:44.847 に答える