3

次のコードで Perl の PDL を試しています。

#!/usr/bin/perl  -w
use strict;
use PDL::Core qw(pdl);
use PDL::Math qw(isfinite);
use PDL::Primitive qw(statsover);


my $div = 4;
my @array1 = (0..10);
my $pdl_array = log(pdl(@array1)/$div);
$pdl_array->where(!isfinite($pdl_array)) .= 0;
my($mean,$stdev) = statsover($pdl_array);
die $pdl_array,"\n",$mean," ",$stdev,"\n";

そして、私はこのエラーが発生しています:

未定義のサブルーチン &PDL::divide が ./compare_const.pl 行 10 で呼び出されました。

何かヒントがあれば教えてください。どうもありがとうございました。

4

3 に答える 3

4

PDL はその設計が特殊であるため、インポート メカニズムが特殊でやや壊れやすいものになっています。各 PDL モジュールは、新しいメソッドを PDL のパッケージに直接挿入することによって、PDL に機能を追加します。この決定は、PDL v2 の設計の非常に早い段階で行われ、その後 10 年間変更されていません。(下位互換性のある方法であっても、変更できない理由はありませんが、PDL 開発者の誰もそうする時間を確保していません。)

その結果、PDL が必要な基本機能を備えていることを確認するために、少数のモジュールをロードする必要があります。PDL の import 関数を見ると、多数のパッケージが呼び出し元の名前空間に明示的に読み込まれていることがわかります。この理由は良いことです --- ディストリビューションを正常に保つために複数のモジュールに機能を分割しています --- しかし、実装は一般的な Perl の慣行に沿っていません。これが、特定の関数を名前空間にインポートしようとして失敗した理由です。

解決策はすでに説明されています。すべてのuse PDL::...ステートメントを単一のuse PDL:

use strict;
use warnings;
use PDL;

my $div = 4;
...

またはuse PDL::Lite(PDLのパッケージが完全であることを確認するために)言ってから、特定の機能を(メイン)パッケージにインポートします

use strict;
use warnings;

use PDL::Lite;
use PDL::Core qw(pdl);
use PDL::Math qw(isfinite);
use PDL::Primitive qw(statsover);

my $div = 4;
...
于 2014-07-03T12:40:33.650 に答える
1

追加するだけuse PDL;で、コードが機能します。

#!/usr/bin/perl  -w
use strict;

use PDL;
use PDL::Core qw(pdl);
use PDL::Math qw(isfinite);
use PDL::Primitive qw(statsover);

my $div = 4;
my @array1 = (0..10);
my $pdl_array = log( pdl(@array1) / $div );
$pdl_array->where(!isfinite($pdl_array)) .= 0;
my ($mean, $stdev) = statsover($pdl_array);
die $pdl_array, "\n", $mean, " ", $stdev, "\n";

出力:

[0 -1.3862944 -0.69314718 -0.28768207 0 0.22314355 0.40546511 0.55961579 0.69314718 0.81093022 0.91629073]
0.112860814716055 0.696414187766251
于 2014-06-30T20:52:43.210 に答える
1

PDL には、ロードする必要がある最低限のセットがあります。これらをすべて適切にロードするには、use PDL(大量のものもエクスポートします) またはuse PDL::Lite.

(何らかの理由で、明示的に PDL::divide を直接呼び出してそのエラーを取得していると思ったので、以下の元の回答。)

元の答え:

なぜそれがうまくいくと思うのですか?

はい、PDL は大量のものをエクスポートします (使用する場合は使用しません) が、それがどこからエクスポートされているかについては保証されません。(実際には、多くの異なる場所から使用中のパッケージに直接エクスポートされているようです。)

名前空間の汚染を回避しようとしている場合は、指定されたパッケージにインポートして、そこからのものを使用することをお勧めします。

{
    package My::PDL;
    use PDL;
}
...
My::PDL::divide...

またはOOインターフェースを使用する(PDL::Liteを参照してください。)

于 2014-06-30T16:56:28.853 に答える