6

我可以创建一个包含“空槽”的数组:

$ 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

但是如何使用[and为匿名数组指定]呢?

这将不起作用:

  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

4 回答 4

6
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."
于 2011-07-03T22:44:53.730 回答
4

那应该这样做:

$a=[];
$#$a=4;

更新(回复@hexcoder):在一个声明中:

$#{$a=[]}=4

在一个返回数组的语句中:

$a = (map(($_,$#$_=4),[]))[0]

虽然,我不建议使用那种结构......

于 2011-07-03T22:27:18.737 回答
1

背景:在我的测试脚本中,我希望能够精确地比较数组内容。例如,我想区分“未分配”和“分配有 undef 值”。

您可以检查索引是否超过末尾。除此之外,您无能为力。

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

打印 10000。undef $x->[9999]相当于$x->[9999] = undef;因为 0 到 9998 的元素都不存在,perl 会神奇地将所有中间元素分配给undef.

于 2011-07-03T22:29:10.353 回答
-1

You can only do that kind of thing from XS code (see for example Devel::Peek). Some, but not all, of it is exposed by the *::Util packages. (I've been working on a debugging/tracing package, so I know more about this than anyone should need to....)

于 2011-07-03T22:13:58.150 回答