简体   繁体   中英

Undefined subroutine &PDL::divide

I'm trying Perl's PDL in the following code:

#!/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";

and I'm getting this error:

Undefined subroutine &PDL::divide called at ./compare_const.pl line 10.

Any hint, please?Thanks a lot.

PDL is unusual in its design, and therefore has an unusual and somewhat fragile import mechanism. Each PDL module adds functionality to PDL by inserting a new method directly into PDL's package . This decision was made very early in the design of PDL v2, and has not been changed in the intervening decade. (There's no reason it couldn't be changed, even in a backward compatible way, but none of the PDL developers have set aside the time to do so.)

As a result, you must load a handful of modules to ensure that PDL has its requisite, basic functionality. If you take a look at PDL's import function, you'll notice thatit explicitly loads a number of packages into the caller's namespace . The reason for this is good---splitting functionality across multiple modules to keep the distribution sane---but the implementation is not aligned with common Perl practices. This is why your attempt to import specific functions into your namespace failed.

The solution has already been explained. Either replace all of your use PDL::... statements with a single use PDL :

use strict;
use warnings;
use PDL;

my $div = 4;
...

or say use PDL::Lite (to ensure that PDL's package is complete) and then import the specific functions into your (main) package

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

PDL has a minimum set of things that must be loaded. To get these all properly loaded, you must either use PDL (which also exports a bunch of stuff) or use PDL::Lite .

(I for some reason thought you were explicitly calling PDL::divide directly and getting that error, hence my original answer below.)

Original answer:

I'm wondering why you think that should work?

Yes, PDL exports a bunch of stuff (if you use it, which you do not), but that doesn't give you any guarantee about where it is exporting it from . (In point of fact, it appears to export from a number of different places directly into the use`ing package.)

If you are trying to avoid namespace pollution, I would recommend either importing into a designated package and using stuff from there:

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

or using the OO interface (see PDL::Lite, I think?)

Just add use PDL; and your code will work:

#!/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";

Outputs:

[0 -1.3862944 -0.69314718 -0.28768207 0 0.22314355 0.40546511 0.55961579 0.69314718 0.81093022 0.91629073]
0.112860814716055 0.696414187766251

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM