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";

我收到了这个错误:

在 ./compare_const.pl 第 10 行调用了未定义的子例程 &PDL::divide。

有什么提示吗?非常感谢。

4

3 回答 3

4

PDL 的设计不寻常,因此具有不寻常且有些脆弱的导入机制。每个 PDL 模块通过将新方法直接插入 PDL 的包中来为 PDL 添加功能。这一决定是在 PDL v2 设计的早期做出的,并且在随后的十年中没有改变。(没有理由不能更改它,即使以向后兼容的方式,但没有一个 PDL 开发人员留出时间来这样做。)

因此,您必须加载少量模块以确保 PDL 具有其必需的基本功能。如果您查看 PDL 的导入函数,您会注意到它显式地将许多包加载到调用者的命名空间中。这样做的原因是好的——在多个模块之间拆分功能以保持分布健全——但实现与常见的 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 导出了一堆东西(如果你使用它,你不使用它),但这并不能保证它从哪里导出它。(事实上​​,它似乎从许多不同的地方直接导出到 use`ing 包中。)

如果您想避免命名空间污染,我建议您导入指定的包并使用那里的东西:

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

或使用 OO 接口(请参阅 PDL::Lite,我认为?)

于 2014-06-30T16:56:28.853 回答