user974896
user974896

Reputation: 1813

How can I pass and return hashes from a sub in Perl?

I've been toying with hashes in Perl. The following works as expected:

use strict;
use warnings;

sub cat {
        my $statsRef = shift;
        my %stats = %$statsRef;

        print $stats{"dd"};
        $stats{"dd"} = "DDD\n";
        print $stats{"dd"};
        return ("dd",%stats);
}

my %test;
$test{"dd"} = "OMG OMG\n";

my ($testStr,%output) = cat (\%test);
print $test{"dd"};

print "RETURN IS ".$output{"dd"} . " ORIG IS ". $test{"dd"};

Output is:

OMG OMG
DDD
OMG OMG
RETURN IS DDD
 ORIG IS OMG OMG

When I add an array into the mix however it errors out.

use strict;
use warnings;  sub cat {
        my $statsRef = shift;
        my %stats = %$statsRef;

        print $stats{"dd"};
        $stats{"dd"} = "DDD\n";
        print $stats{"dd"};         return ("dd",("AAA","AAA"),%stats); }
 my %test; $test{"dd"} = "OMG OMG\n";

my ($testStr,@testArr,%output) = cat (\%test);
print $test{"dd"};

print "RETURN IS ".$output{"dd"} . " ORIG IS ". $test{"dd"}. " TESTARR IS ". $testArr[0];

The output is:

OMG OMG
DDD
OMG OMG
Use of uninitialized value in concatenation (.) or string at omg.pl line 20.
RETURN IS  ORIG IS OMG OMG
 TESTARR IS AAA

Why is the array displaying but the hash is not?

Upvotes: 1

Views: 416

Answers (2)

beresfordt
beresfordt

Reputation: 5222

in addition to the answer by raina77ow I would highly recommend just passing references about, rather than translating from type to reference and back again. It's a lot easier to read and less hassle to code (imho)

use Data::Dumper;
use strict;
use warnings;
sub cat {
    my $statsRef = shift;
    print $statsRef->{"dd"} ;
    $statsRef->{"dd"} = "DDD\n";
    print $statsRef->{"dd"} ;
    return ("dd",["AAA","AAA"],$statsRef); 
}

my $test = {} ;
$test->{"dd"} = "OMG OMG\n";

my ( $var, $arrRef, $hashRef ) = cat($test) ;

print "var " . Dumper($var) . "\n" ;
print "arrRef " . Dumper($arrRef) . "\n";
print "hashRef " . Dumper($hashRef) . "\n";

Upvotes: 4

raina77ow
raina77ow

Reputation: 106385

All lists got automatically flattened in Perl. Therefore the assignment operator won't be able to magically distinguish the border between the lists returned by your subroutine. In your case it means that @testArr will consume the resulting list given by cat, and %output will get none of it - hence the Use of unitialized value... warning.

If you need to return a hash or array specifically, use references:

return ("dd", ["AAA", "AAA"], \%stats);

... and later, in the assignment:

my ($testStr, $testArrayRef, $testHashRef) = cat(...);
my @testArray = @$testArrayRef;
my %testHash  = %$testHashRef;

Upvotes: 7

Related Questions