我想从sub返回几个数组和哈希值。当我执行sub时,第一个输出数组将所有输出包装为toguether,其他输出数组保持为空。请看这个例子:
主文件script.pl有:
use mymodule;
my (@o1, $o2)=mymodule::mysub;
print "o1 gives ".$o1[0]." ".$o1[1]." ".$o1[2];
print ", and o2 gives ".$o2." \n";
文件mymodule.pm看起来像:
package mymodule;
sub mysub{
my @a = ('a', 'b');
my $b = 4;
return (@a, $b);
};
1;
运行script.pl将返回o1给出b 4,o2给出。
如您所见,(@ o1,$ o2)与模块返回的值(@ a,$ b)的对应关系不会被保留。
有人可以帮我吗? 很多!
my ($o1_ref, $o2)=mysub;
my @o1 = @{$o1_ref};
print "o1 has ".$#o1." elements, o2 has ".$#o2." elements\n";
print "the first element of o1 is ".$o1->[0]."\n";
sub mysub{
my @a = ('a', 'b');
my $b = 4;
return (\@a, $b);
};
将返回
o1 has -1 elements, o2 has -1 elements
the first element of o1 is
因此它对我的perl 5.14不起作用。
答案 0 :(得分:6)
是时候了解References。
在Perl中,您可以从子例程返回单个列表项目,或者使用单个列表项目进行导入。只有一个列表,所以如果我尝试返回两个数组,Perl会将它们放入一个无差别的列表中:
use strict;
use warnings;
use feature qw(say);
my (@a, @b) = foo();
say join ": ", @a;
say join ": ", @b;
sub foo {
my @first = qw(one two thee);
my @second = qw(uno dos tres);
return (@first, @second);
}
如果您运行此操作,则会看到所有数据都返回到@a
,而@b
中没有任何数据。
引用允许您绕过此限制。引用只是指向内存中实际包含数据的位置的指针。该数据可以是标量($foo
),数组(@foo
)或散列(%foo
)。由于内存中的位置是单个数据位,因此引用允许您拥有一个包含对其他数组的引用的数组,从而为您提供数组数组。或者哈希数组,哈希哈希,或者各种更复杂的数据结构。
让我们看一下你的模块并稍微修改它的代码:
sub mysub{
my @a = ('a', 'b');
my $b = 4;
return (\@a, $b); # Look I added a backslash!
};
1;
反斜杠说我没有返回数组。相反,我在内存中返回该阵列所在的位置。
现在我的程序可以执行此操作:
my ($o1_ref, $o2) = mymodule::mysub(); # We'll talk about this later..
代码中的另一个细微变化。我正在返回的第一个项目不是数组,而是对数组的引用。现在,我所要做的就是取消引用它(允许我访问数组):
my @o1 = @{ $o1_ref };
通过将数据结构的符号放在引用前面来取消引用。你甚至可以做到这一点:
my @o1 = @$o1_ref;
我不喜欢这样,因为很容易错过@$
组合。使用花括号强调您要取消引用数组引用。
现在,你的程序的其余部分应该可以工作。
查看Exporter模块。它是Perl附带的标准模块。
这将允许您从模块中导出您的功能,因此您不必在其前面加上模块的名称:
package Mymodule; # Custom says to give modules capital names.
use strict;
use warnings;
use Exporter qw(import);
our @EXPORT_OK = qw(mysub); # A list of all the subroutines you want main to use
sub mysub { 我的@a = qw(a b); 我的$ b = 4; return(\ @a,$ b); } 1;
现在,您所要做的就是在主程序中说mysub
:
use strict;
use warnings;
use Mymodule qw(mysub); # Include a list of what you want imported
use feature qw(say); # Better "print" than "print"
my ($o1_ref, $o2) = mysub();
my @01 = @{ $o1_ref };
say "o1 gives ".$o1[0]." ".$o1[1]." ".$o1[2];
这是你的代码:
my ($o1_ref, $o2)=mysub;
my @o1 = @{$o1_ref};
print "o1 has ".$#o1." elements, o2 has ".$#o2." elements\n";
print "the first element of o1 is ".$o1->[0]."\n";
sub mysub{
my @a = ('a', 'b');
my $b = 4;
return (\@a, $b);
};
@o2
,因此$#o2
无效。$#
返回LAST索引而不是项目数。使用scalar
函数获取数组中的项目数。@o1
。我这样做是为了简化问题。现在,当您执行$o1->[0]
时,您将取消引用引用的项目。顺便说一句$o1
不作为变量存在。strict
和warnings
个pragma。使用这些错误时会发现很多错误。say
代替打印。你又忘了\n
了。如果您要这样做,请将say
与use feature qw(say);
use strict;
use warnings;
use feature qw(say);
my ($o1_ref, $o2) = mysub();
my @o1 = @{$o1_ref};
say "\@o1 has " . scalar @o1 . " elemenets";
say "The first element of \@o1 is '$o1[0]'";
say "The second element of \@o1 is '$o1[1]'";
say "\$o2 is equal to '$o2'";
sub mysub{
my @a = ('a', 'b');
my $b = 4;
return (\@a, $b);
};
输出:
@o1 has 2 elemenets
The first element of @o1 is 'a'
The second element of @o1 is 'b'
$o2 is equal to '4'
一切正确。
答案 1 :(得分:2)
或传回数组引用
#!/usr/bin/perl
sub mysub{
my @a = ('a', 'b');
my $b = 4;
return (\@a, $b);
};
my ($o1, $o2) = mysub();
print "o1 gives ".${$o1}[0]." ".${$o1}[1]." ".$o1[2];
print ", and o2 gives ".$o2." \n";
答案 2 :(得分:1)
你这样做的方式不适用于Perl。 @a
已展开,只是包含@a
和$b
的列表的第一部分。
分配列表中的数组“greedy”。这有效:
my ( $o2, @o1 ) = gimme();
但这不是:
my ( @o1, $o2 ) = gimme();
因为所有内容都已分配给@o1
。然而,标量优先分配列表从列表中拉出第一个返回并将其分配给标量$o2
,其余分配给@o1
。
答案 3 :(得分:0)
Perl无法从sub返回数组。相反,将@a作为arrayref返回如下:
package mymodule;
sub mysub{
my @a = ('a', 'b');
my $b = 4;
return (\@a, $b);
};
使用arrayref,如下所示:
use mymodule;
my ($o1, $o2)=mymodule::mysub;
print "o1 gives ".$o1->[0]." ".$o1->[1]." ".$o1->[2];
print ", and o2 gives ".$o2." \n";
Bonus:如果你需要arrayref的最后一个元素的索引(也许你想迭代通过arrayref构建一个数组?):
$last_index = $#$o1;
正如其他人推荐的那样,我建议您了解Perl References。