Неопределенная подпрограмма &PDL:: разделяй

Я пытаюсь 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:: split вызывается в./compare_const.pl строка 10.

Любой намек, пожалуйста? Большое спасибо.

3 ответа

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

Просто добавь 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

PDL имеет минимальный набор вещей, которые должны быть загружены. Чтобы загрузить все это правильно, вы должны либо use PDL (который также экспортирует кучу вещей) или use PDL::Lite,

(Я по какой-то причине подумал, что вы явно вызываете PDL:: split напрямую и получаете эту ошибку, поэтому мой оригинальный ответ ниже.)

Оригинальный ответ:

Мне интересно, почему вы думаете, что это должно работать?

Да, PDL экспортирует кучу вещей (если вы их используете, а вы нет), но это не дает вам никакой гарантии относительно того, откуда они экспортируют. (На самом деле, кажется, что он экспортируется из нескольких разных мест непосредственно в пакет использования).

Если вы пытаетесь избежать загрязнения пространства имен, я бы порекомендовал либо импортировать в назначенный пакет, либо использовать что-то оттуда:

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

или используя интерфейс OO (я думаю, см. PDL::Lite?)

Другие вопросы по тегам