Как создать анонимный массив ([]) с «пустыми слотами»? - PullRequest
5 голосов
/ 04 июля 2011

Я могу создать массив с пустыми слотами:

$ perl -wde 1
...
  DB<1> $x[2] = 0
  DB<2> x \@x
0  ARRAY(0x103d5768)
   0  empty slot
   1  empty slot
   2  0

или

  DB<3> $#y = 4
  DB<4> x \@y  
0  ARRAY(0x103d5718)
   0  empty slot
   1  empty slot
   2  empty slot
   3  empty slot
   4  empty slot

Обратите внимание: это не то же самое, что присвоение undef.

Но как мне указать это для анонимного массива, используя [ и ]?

Это не будет работать:

  DB<5> x [,,0]
syntax error at (eval 27)[/usr/local/lib/perl5/5.10.0/perl5db.pl:638] line 2, near "[,"

И это тоже не получается, так как я получаю только назначенное значение:

  DB<6> x []->[2] = 0
0  0

Бонусный вопрос: как я могу проверить наличие "пустого слота массива" в моем скрипте Perl?

Справочная информация. В моих тестовых сценариях я хотел бы иметь возможность точно сравнивать содержимое массива. Например, я хочу различать «не назначено» и «назначено со значением undef».

Спасибо за любые идеи.

Ответы [ 4 ]

5 голосов
/ 04 июля 2011
use feature qw/ say /;
use strict;
use warnings;

my $aref;

$#{$aref} = 4;
$aref->[2] = undef;
$aref->[3] = '';

foreach my $idx ( 0 .. $#{$aref} ) {
    say "Testing $idx.";
    say "\t$idx exists." if exists $aref->[$idx];
    say "\t$idx defined." if defined $aref->[$idx];
}

OUTPUT:
Testing 0.
Testing 1.
Testing 2.
    2 exists.
Testing 3.
    3 exists.
    3 defined.
Testing 4.

Мы предварительно выделили пять мест в анонимном массиве @{$aref}.Верхний индекс - 4.Мы можем найти верхний индекс так же, как мы его создали;путем проверки значения $#{$aref}.Мы можем проверить на существование.Мы знаем, что все между 0 и 4 было создано.Но Perl сообщает, что «существует» только для элементов массива, которым определенно было что-то назначено (даже если это undef).Следовательно, $aref->[2], как сообщается, существует, но не определен.Ради интереса, мы присвоили '' $aref->[3], чтобы увидеть отчет об испытаниях, определенный один раз.Но короткая история заключается в том, что, хотя массив предварительно расширен, мы все равно можем проверить разницу между элементом, инициализируемым с помощью undef, и элементом, являющимся undef посредством предварительного расширения массива, используя 'exists '.

Не могу сказать, что это задокументированное поведение exists.Так что нет никаких гарантий, что когда-нибудь это не изменится.Но он работает на 5.8, 5.10, 5.12 и 5.14.

Итак, ищем простой способ найти, какие элементы были инициализированы, какие определены, а какие нет, вот пример:

use feature qw/ say /;
use strict;
use warnings;

my $aref;

$#{$aref} = 4;
$aref->[2] = undef;
$aref->[3] = '';

my @initialized = grep { exists $aref->[$_] } 0 .. $#{$aref};
my @defined = grep { defined $aref->[$_] } 0 .. $#{$aref};
my @uninitialized = grep { not exists $aref->[$_] } 0 .. $#{$aref};
my @init_undef = grep { exists $aref->[$_] and not defined $aref->[$_] } 0 .. $#{$aref};
say "Top index is $#{$aref}.";
say "These elements are initialized: @initialized.";
say "These elements are not initialized: @uninitialized.";
say "These elements were initialized with 'undef': @init_undef.";
say "These elements are defined: @defined."
3 голосов
/ 04 июля 2011

Что должно сделать:

$a=[];
$#$a=4;
1 голос
/ 04 июля 2011

Справочная информация: в моих тестовых сценариях я хотел бы иметь возможность точно сравнивать содержимое массива.Например, я хочу провести различие между «не назначено» и «назначено со значением undef».

Вы можете проверить, находится ли индекс после конца.Кроме того, вы мало что можете сделать.

$x = [];
undef $x->[9999];
print scalar @$x;

печатает 10000. undef $x->[9999] эквивалентно $x->[9999] = undef; Поскольку ни один из элементов от 0 до 9998 не существует, perl волшебным образом назначит все промежуточныеэлементы к undef.

0 голосов
/ 04 июля 2011

Вы можете делать такие вещи только из кода XS (см., Например, Devel::Peek).Некоторые, но не все, доступны пакетам *::Util.(Я работал над пакетом отладки / трассировки, поэтому я знаю об этом больше, чем кто-либо должен был бы ....)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...