所以我有一个包含数组的对象:
package MyObject;
sub new {
my($type) = @_;
my $self->{Params}{Status}{Packages} = [];
}
我有一个新的包子附加到这个"包"数组如:
sub add_package {
my($self, $package_obj) = @_;
push $self->{Params}{Status}{Packages}, $package;
}
现在当我去找我的阵列中的所有软件包时,我遇到了问题。每当我尝试拉出这样的包时:
foreach my $package($self->{Params}{Status}{Packages}) {
# do something with $package.
}
这只循环一次。根据我的理解,哈希实际上存储了一个指向数组的指针,所以我试着这样做:
foreach my $package(@$self->{Params}{Status}{Packages}) {
# do something with $package.
}
但是有一个错误说$ self不是一个数组。我确实注意到了:
scalar $self->{Params}{Status}{Packages};
它返回:
@ARRAY(0xSome Address);
我错过了什么?我如何使用foreach
循环来浏览我的数组?
答案 0 :(得分:4)
$self->{Params}{Status}{Packages}
是数组的reference。当你引用某个东西时,把正确的字符放在它前面dereference it。如果引用不只是一个名称,前面可能有一些符号,则需要用括号括起来。这是一个优先问题:@$self->{Params}{Status}{Packages}
被解析为(@$self)->{Params}{Status}{Packages}
,但您需要
@{$self->{Params}{Status}{Packages}}
即。表达式$self->{Params}{Status}{Packages}
引用的数组。
答案 1 :(得分:3)
在这种情况下,您需要将它全部包装在数组解除引用块@{}
中,以便perl知道您尝试取消引用哪个部分...
for my $package (@{ $self->{Params}{Status}{Packages} }){
print "$package\n";
}
另外,为了保持一致,我更喜欢在提取或插入时始终使用块来解析数组:
push @{ $self->{Params}{Status}{Packages} }, $package;
更新:从5.24.0 +开始,autoderef(使用keys()
,values()
或each()
带参考)几乎肯定会被删除,并替换为后缀引用。但是,使用@{}
和%{}
将继续受到支持,并且向后兼容,因此我建议您始终使用它们。
答案 2 :(得分:1)
在我看来,最明智的方法是将数组引用提取到临时标量变量,这使得访问数组变得非常简单
my $packages = $self->{Params}{Status}{Packages};
for my $package ( @$packages ) {
# do something with $package.
}
此外,如果您已启用use strict
和use warnings
,则add_package
子例程将生成消息
push on reference is experimental
这不是你可以放心忽视的事情。实验性功能可能会在更高版本的Perl中改变其行为或完全消失,在生产代码中使用它们是不明智的。你可以用类似的方式修复你的子程序,比如这个
sub add_package {
my ($self, $package_obj) = @_;
my $packages = $self->{Params}{Status}{Packages};
push @$packages, $package;
}