我正在使用以下代码尝试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行调用。
请提示吗?非常感谢。
答案 0 :(得分:4)
PDL在设计上是不寻常的,因此具有不寻常且有些脆弱的导入机制。每个PDL模块通过inserting a new method directly into PDL's package向PDL添加功能。这个决定是在PDL v2设计的早期阶段做出的,并且在这十年间没有改变。 (即使以向后兼容的方式,也没有理由不改变它,但是没有一个PDL开发人员留出时间这样做。)
因此,您必须加载一些模块以确保PDL具有必需的基本功能。如果您查看PDL的导入功能,您会注意到it explicitly loads a number of packages into the caller's namespace。这样做的原因很好 - 跨多个模块分离功能以保持分布正常 - 但实现与常见的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;
...
答案 1 :(得分:1)
PDL有一组必须加载的东西。要正确加载这些内容,您必须use PDL
(也导出一堆内容)或use PDL::Lite
。
(我出于某种原因认为你明确地直接调用了PDL :: divide并得到了这个错误,因此我的原始答案如下。)
原始答案:
我想知道为什么你认为应该工作?
是的,PDL导出一堆东西(如果你使用它,你没有),但是这并不能保证从导出它的位置。 (事实上,它似乎从许多不同的地方直接导入到使用包中。)
如果你试图避免命名空间污染,我建议你导入指定的包并使用那里的东西:
{
package My::PDL;
use PDL;
}
...
My::PDL::divide...
或使用OO界面(参见PDL :: Lite,我认为?)
答案 2 :(得分: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