我正在尝试理解perldsc文档中的“常见错误”部分。当他提到时,作者试图传达的是什么:
构造类似数组的两个最常见的错误是要么意外地计算元素的数量,要么重复引用相同的内存位置。在这种情况下,您只需获取计数而不是嵌套数组:
for my $i (1..10) {
my @array = somefunc($i);
$AoA[$i] = @array; # WRONG!
}
根据我的理解,当它迭代时,它将取第一个值(1..10),即1,并将它传递给这样的函数:
my @array = somefunc(1);
由于未定义该功能,我将创建逻辑。
sub somefunc {
my $a = shift;
print $a * $a;
}
基本上会这样做:
1 * 1
,结果为'1'。
据我所知,我的@array看起来像:
@array = ('1');
下一行将会:
$AoA[$i] = @array;
我假设$ AoA [$ 1]是一个匿名数组(他/她没有用'my',btw声明),@ array将是这个匿名数组的第一个元素,作者说它错了。并为每个循环迭代到'2'。
somefunc(2);
这将是'4'并传递给:
$AoA[$i] = @array
使用此代码的作者有什么意义呢?我试图理解错误,但更重要的是,我正在努力理解代码。任何帮助将不胜感激。
更新
我想我理解为什么这是一个常见的错误,因为当我使用print和Dumper时,我可以直观地看到作者试图传达的内容,这是修改后的代码。
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
for my $i (1..10) {
my @AoA;
my @array = somefunc($i);
print "The array is Dumper(@array)\n";
$AoA[$i] = @array; # WRONG!
print Dumper($AoA[$i]);
}
sub somefunc {
my $a = shift;
return $a * $a;
}
在perldoc perldsc的Common Mistakes段落中,他/她陈述
在这种情况下,您只需获取计数而不是嵌套数组:
以下是翻斗车的输出。
The array is Dumper(1)
$VAR1 = 1;
The array is Dumper(4)
$VAR1 = 1;
The array is Dumper(9)
$VAR1 = 1;
The array is Dumper(16)
$VAR1 = 1;
The array is Dumper(25)
$VAR1 = 1;
The array is Dumper(36)
$VAR1 = 1;
The array is Dumper(49)
$VAR1 = 1;
The array is Dumper(64)
$VAR1 = 1;
The array is Dumper(81)
$VAR1 = 1;
The array is Dumper(100)
$VAR1 = 1;
所以我假设重复了
$VAR1 = 1;
是计数而不是嵌套数组。
作者确实指出,如果计数是我真正想要的,那么就像这样重写代码:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
for my $i (1..10) {
my @count;
my @array = somefunc($i);
print "The array is Dumper(@array)\n";
$count[$i] = scalar @array;
print Dumper($count[$i]);
}
sub somefunc {
my $a = shift;
return $a * $a;
}
但文档没有告诉我如何获取嵌套数组?
更新
如果我错了,请纠正我,但我重写了代码以获取嵌套数组:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my @count;
my @new_array;
for my $i (1..10) {
#my @count;
my @array = somefunc($i);
push @new_array, [@array];
}
sub somefunc {
my $a = shift;
return $a * $a;
}
print Dumper(\@new_array);
哪个印刷
$VAR1 = [
[
1
],
[
4
],
[
9
],
[
16
],
[
25
],
[
36
],
[
49
],
[
64
],
[
81
],
[
100
]
];
答案 0 :(得分:6)
在以下声明中:
$AoA[$i] = @array;
标量上下文中引用了@array
,产生了许多元素。上下文由LHS强加,即$AoA[$i]
,它是@AoA
数组的单个元素。
在Perl中,严格意义上没有数组数组。它们基本上由“扁平”数组或带引用的数组模拟。对于后者,您需要使用take reference运算符,如:
$AoA[$i] = \@array;
对于入门者,您可能会发现,Data::Dumper
在检查复杂数据结构(如arrayrefs和hashrefs)时非常方便。
答案 1 :(得分:1)
Perl是多态的,这意味着它透明地处理不同的数据类型,并且通常可以很好地猜测如何处理某些事情。这使得程序员的工作变得更加容易,因为它不像其他语言那样强类型化。
因此,例如,如果$ i是数字4,您可以这样做:
print $i + 1;
你会看到一个5 - 很合乎逻辑,对吗?
如果你这样做:
print "I am " , $i , " years old";
你会看到"我4岁" - 在这种情况下perl说"你在列表上下文中操作,所以我将$ i视为一个字符串。无需像许多其他语言所坚持的那样将数字转换为字符串。
所以当你指定
时$AoA[$i] = @array;
它对待它的方式取决于上下文。在标量上下文中,它将$ AoA [$ i]设置为数组的长度。
有关标量与列表上下文的更多信息,请阅读以下答案:
答案 2 :(得分:1)
你的例子对于理解这里发生的事情并不是很有用,因为你的子程序总是返回“1” - 调用print()
的结果。如果您将print()
替换为return()
,那么您将获得不同的值(1,4,9等)。
但下一行代码:
$AoA[$i] = @array;
始终将1
分配给@Aoa
的元素。那是因为您正在为标量变量(@array
)分配一个数组($AoA[$i]
),当您在标量上下文中计算数组时,您将获得数组中元素的数量。
现在,由于您的@array
只有一个元素,您可以这样做:
$AoA[$i] = $array[0];
但这并不是真正构建一个数组数组。你真正想做的是获得一个数组的引用。
$AoA[$i] = \@array;
如果子程序返回多个值,这将更有用。
sub somefunc {
# Used $x instead of $a as $a has a special meaning in Perl
my $x = shift;
return ($x * $x, $x * $x * $x);
}
for my $i (1..10) {
my @array = somefunc($i);
$AoA[$i] = \@array;
}
作为探索此问题的有用工具是https://facebook.github.io/react-native/docs/navigator.html。尝试添加:
use Data::Dumper;
到代码的顶部,然后:
print Dumper @AoA;
在foreach
循环之后,查看您获得的不同数据结构。