perl - Perl5: returning several arrays/hashes from a sub -
i wanna return several arrays , hashes sub. when execute sub, first output array wraps outputs toguether , others keep empty. pls see example:
the main file script.pl has:
use mymodule; (@o1, $o2)=mymodule::mysub; print "o1 gives ".$o1[0]." ".$o1[1]." ".$o1[2]; print ", , o2 gives ".$o2." \n";
file mymodule.pm looks like:
package mymodule; sub mysub{ @a = ('a', 'b'); $b = 4; return (@a, $b); }; 1;
running script.pl return o1 gives b 4, , o2 gives .
as see, correspondence of (@o1, $o2) values (@a, $b) returned module not preserved.
can me here? thx lot!
thx explanation. cannot obtain aimed result thru suggestion. code:
my ($o1_ref, $o2)=mysub; @o1 = @{$o1_ref}; print "o1 has ".$#o1." elements, o2 has ".$#o2." elements\n"; print "the first element of o1 ".$o1->[0]."\n"; sub mysub{ @a = ('a', 'b'); $b = 4; return (\@a, $b); };
will return
o1 has -1 elements, o2 has -1 elements first element of o1
thus not work perl 5.14.
it's time learn references.
in perl, can return a single list of items subroutine or have a single list of items import. single list, if attempt return 2 arrays, perl put them single undifferentiated list:
use strict; use warnings; use feature qw(say); (@a, @b) = foo(); join ": ", @a; join ": ", @b; sub foo { @first = qw(one 2 thee); @second = qw(uno dos tres); return (@first, @second); }
if run this, see of data returned @a
, nothing in @b
.
references allow around restriction. reference pointer place in memory contains data. data scalar ($foo
), array (@foo
), or hash (%foo
). since location in memory single bit of data, references allow have array contains references other arrays giving array of arrays. or array of hashes, or hash of hashes, or sorts of more complex data structures.
let's @ module , modify it's code wee bit:
sub mysub{ @a = ('a', 'b'); $b = 4; return (\@a, $b); # added backslash! }; 1;
that backslash says not returning array. instead, returning location in memory array lives.
now program can this:
my ($o1_ref, $o2) = mymodule::mysub(); # we'll talk later..
another slight change in code. first item i'm returning isn't array, reference array. now, have dereference (that allows me access array):
my @o1 = @{ $o1_ref };
you dereference putting sigil of data structure in front of reference. have done this:
my @o1 = @$o1_ref;
i don't because it's easy miss @$
combination. using curly braces emphasizes dereferencing array reference.
now, rest of program should work.
bonus advice
take @ exporter module. it's standard module comes perl.
this allow export functions module, don't have prefix module's name:
package mymodule; # custom says give modules capital names. use strict; use warnings; use exporter qw(import); our @export_ok = qw(mysub); # list of subroutines want main use
sub mysub { @a = qw(a b); $b = 4; return (\@a, $b); } 1;
now, have mysub
in main program:
use strict; use warnings; use mymodule qw(mysub); # include list of want imported use feature qw(say); # better "print" "print" ($o1_ref, $o2) = mysub(); @01 = @{ $o1_ref }; "o1 gives ".$o1[0]." ".$o1[1]." ".$o1[2];
in response this
here's code:
my ($o1_ref, $o2)=mysub; @o1 = @{$o1_ref}; print "o1 has ".$#o1." elements, o2 has ".$#o2." elements\n"; print "the first element of o1 ".$o1->[0]."\n"; sub mysub{ @a = ('a', 'b'); $b = 4; return (\@a, $b); };
- there's no array
@o2
,$#o2
invalid. $#
returns last index , not number of items. usescalar
function number of items in array.- you've dereferenced
@o1
. did simplify problem. now, you're dereferencing deferenced item when$o1->[0]
. way$o1
doesn't exist variable. - always use
strict
,warnings
pragmas. you'd catch lot of errors when use these. - use
say
instead of print. forgot\n
on end again. if you're going that, usesay
use feature qw(say);
corrected code
use strict; use warnings; use feature qw(say); ($o1_ref, $o2) = mysub(); @o1 = @{$o1_ref}; "\@o1 has " . scalar @o1 . " elemenets"; "the first element of \@o1 '$o1[0]'"; "the second element of \@o1 '$o1[1]'"; "\$o2 equal '$o2'"; sub mysub{ @a = ('a', 'b'); $b = 4; return (\@a, $b); };
the output:
@o1 has 2 elemenets first element of @o1 'a' second element of @o1 'b' $o2 equal '4'
all correct.
Comments
Post a Comment