my @a=[[1]];
print $a[0][0];
**output**
ARRAY(0x229e8)
为什么它打印出一个
ARRAY
而不是1
?我原本期望@a
创建一个大小为1的数组,并引用另一个仅包含一个元素1
的数组。这里的问题比较棘手。你将 @a
赋值为一个包含对数组引用的引用的列表,比你预期的多了一层间接引用。
如果想要得到期望的结果,你应该这样写:
@a = ( [ 1 ] );
你想要的值在 $a[0][0][0]
。你正在将一个数组引用赋值为@a
数组的第一个元素。
这是类似的事情:
my @a = 'scalar';
这将创建一个仅有1个元素的数组,其中该元素为字符串'scalar'
。因此,当您将标量值赋给数组时,Perl会尝试按照您的意愿创建一个大小为1的列表,并将该标量值作为第一个元素。
另外,
my @a = undef;
这段代码做的是相同的事情,但第一个槽位是undef
。你想要的是
my @a = [1];
我猜您想要写的是:
my $x = [[1]]; # reference to anon array containing
# reference to anon array with one element
print $x->[0][0];
$x->[0]->[0]
是我喜欢的写法。 - Dan Beam[]
表示数组和数组引用容易导致混淆,但正如我所说-这并不特别重要。 - Dan Beammobrule、Axeman和Sinan都回答了你的问题:你创建了一个三层深度的数据结构,而不是两层。
我很惊讶没有人建议使用核心Data::Dumper库来帮助理解数据结构问题。
use Data::Dumper;
my @a = [[1]];
print Dumper \@a;
这将打印:
$VAR1 = [ [ [ 1 ] ] ];
你的错误是使用数组引用构造函数[]
,而不是只使用括号(或什么都不使用)。@a = ([1]);
那么,为什么Perl有奇怪的[]
和{}
语法来声明哈希和数组引用呢?
这归结于Perl会展开列表。这意味着如果你说:@a = (@b, @c);
,那么@a
被赋值为@b
的内容与@c
的内容相连的结果。这与Python的extend
列表方法相同。如果你想让@a
有两个元素,你需要强制它们不要扩展。你可以通过对每个数组取一个引用来实现这一点:@a = (\@b, \@c);
。这就像Python的append
列表方法。
当你想创建匿名嵌套结构时,你需要有一种方法来标记它们是哈希还是数组。这就是我上面提到的语法的作用。
但是列表展开有什么好处呢?为什么值得为了制作数组和哈希引用而使用与正常初始化不同的不寻常语法呢?
列表展开意味着你可以轻松地在一个变量中组装一系列子例程参数,然后将它们传递而不需要做任何棘手的事情:foo(@some_args, 5, @more_args);
。请参阅维基百科上关于此概念在其他语言中如何工作的信息。你可以使用map
和其他函数做各种好玩的事情。