Xhings has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks, I am trying to pass an array to a subroutine and trying to collect three hashes created by it. Following is the code:

sub ParseForExpDB2Params{ my %ExpValHash1; my %ExpValHash2; my %ExpValHash3; my $x = 0; my $i = 0; my $y = 0; my @param = @_; my $val = ""; do something; .... ..... print Dumper(\%ExpValHash1); print "--------------------------------\n"; print Dumper(\%ExpValHash2); print "--------------------------------\n"; print Dumper(\%ExpValHash3); return (\%ExpValHash1,\%ExpValHash2,\%ExpValHash3); }

I am calling the subroutine as below:

my (%ExpValHash4, %ExpValHash5, %ExpValHash6) = ParseForExpDB2Params(@ +params);

Now inside the subroutine when i am dumping I get all the key value pairs but outside, its indicating no value. I am sure I am missing something but not able to figure it out. Please enlighten me. Thanks, Xhings

Replies are listed 'Best First'.
Re: Returning multiple Hash references from a sub()
by Anonymous Monk on Sep 03, 2010 at 12:21 UTC
    Instead, use: my ($foo, $bar, $baz) = ParseForExpDB2Params(@params);

    References are scalars. Assigning a (part of a) list to an array or hash puts all remaining scalars in that list into that array or hash, even if the left-hand side of the assignment has more than one variable.

    Example: ($foo, @bar, @baz) = (1..10); results in $foo containing 1, @bar containing the list equivalent to (2..10), and @baz containing nothing (it was assigned an empty list, so any contents were overwritten).

    Additionally, with warnings enabled, you would receive a warning about an odd (3) number of elements assigned to a hash, which requires an even number of elements (key-value pairs).

      In additional to AnonMonks excellent explanation I'd like to point you to perlreftut, which introduces you to the sublteties of references in Perl 5.

      Another good document is the Perl Data Structures Cookbook.

      Perl 6 - links to (nearly) everything that is Perl 6.
Re: Returning multiple Hash references from a sub()
by JavaFan (Canon) on Sep 03, 2010 at 16:42 UTC
    You are returning a list (of hashrefs) from the sub. You're assigning the list to a hash (the other hashes will be empty). You need to do it in multiple steps:
    my @out = ParseForExpDB2Param(@params); my %ExpValHash4 = %{$out[0]}; my %ExpValHash5 = %{$out[1]}; my %ExpValHash6 = %{$out[2]};
    Or just work with hashrefs:
    my ($ExpValHash4, $ExpValHash5, $ExpValHash6) = ParseForExpDB2Param(@p +arams);
Re: Returning multiple Hash references from a sub()
by locked_user sundialsvc4 (Abbot) on Sep 03, 2010 at 14:14 UTC

    I tend to return a hashref, where each element in the hash contains a reference to something else.   (I choose to do so because that way each element is named, and that seems to work better as the code inevitably continues to expand.)   But the alternative of returning a list is a good one, too.   The each() function, for example, does this.

    TMTOWTDI.   But, no matter what WTDI you eventually choose, make it abundantly clear, well documented, and maintainable.

      If you need to return more than three hash refs, you can also start asking yourself if it wouldn't be clearer to return an object of some kind. (Often the answer is still "no", but not always).