Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Returning two hashes from a sub?

by matija (Priest)
on Mar 01, 2004 at 15:25 UTC ( #332938=perlquestion: print w/replies, xml ) Need Help??

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

I have a subroutine which needs to return two hashes. Obviously, if it just said return (%a,%b) it wouldn't work. So I must return references to hashes.

The thing is, I don't want references to hashes later in the program (Lazy).

So far, I could only think of doing something like:

my ($first,$second)=routine(); my %first=%{$first}; my %second=%{$second};
I have considered passing the two hashes to the subroutine as parameters, and then in the subroutine assigning values to $_[0], but I would prefer not to do that because I don't find it very readable.

I've looked for inspiration in perldoc perlref, but I found none. And yet I feel that there must be a way to do it.

Replies are listed 'Best First'.
Re: Returning two hashes from a sub?
by Limbic~Region (Chancellor) on Mar 01, 2004 at 15:31 UTC
    Actually you could return two hashes from the sub - the problem would be on the receiving end. It would not know where to stop slurping. There are two ways to be lazy.

    The first is create the hashes outside of the sub and pass them into the sub by reference. There would be no need to return the references since the hashes would already be modified. Just start using them after the sub is finished.

    The second is even lazier. Create the hashes outside of the sub but at a scope level the sub can see. Modify the hashes inside the sub so when it finishes - you can start using them.

    Cheers - L~R
Re: Returning two hashes from a sub?
by esskar (Deacon) on Mar 01, 2004 at 15:53 UTC
    I think using the parameters is the best choice
    sub routine { my ($hashref1, $hashref2) = @_; # don't convert them back to hashes # work with the refs instead, so you won't have to # set @_ at the end } my %first, %second; routine(\%first, \%second);
Re: Returning two hashes from a sub?
by davido (Cardinal) on Mar 01, 2004 at 16:23 UTC
    Well, the way discussed in perlsub is simply to pass by reference.

    That being the case, your snippet is pretty much how its done. Try not to get too hung up on the idea that your hash is known by reference rather than by name. There's really not much difference in how you write your code; you just dereference the references, that's all.

    my ( $first, $second ) = routine(); print "$_\n" for keys %{$first}; print "$first->{Key1}\n"; # etc.....

    If you start out using a reference to an anonymous hash, never naming your hash in the first place, you'll never need to worry about copying it back and forth between named hashes and referenced hashes.


Re: Returning two hashes from a sub?
by revdiablo (Prior) on Mar 01, 2004 at 18:52 UTC

    In my opinion, the thing to do is return hashrefs, and use them directly. I don't see how laziness affects your decision on this either way, unless you don't want to type a few extra syntax characters. If that's the reason, I fear you've given in to the wrong kind of laziness...

    That said, if you insist on using "real" hashes, then what you've got is probably the simplest and most straightforward way to do so. Why fight it? 8^)

Re: Returning two hashes from a sub?
by BrowserUk (Pope) on Mar 01, 2004 at 22:27 UTC

    There is a technique mentioned in perlsub for dealing with this. Although it may be seen as old-fashioned, it still works fine, and allows you to deal with "real hash" syntax inside and outside the sub without resorting to global vars or en masse copying of data.

    #! perl -sw use strict; sub getRefs{ my( %h1, %h2 ); @h1{ qw[the quick brown fox] } = (1..4); @h2{ 'a'..'z' } = 1 .. 26; return \%h1, \%h2; } { our( %glob1, %glob2 ); local( *glob1, *glob2 ) = getRefs(); print "$_ $glob1{ $_ }\n" for keys %glob1; print "$_ $glob2{ $_ }\n" for keys %glob2; } __DATA__ the 1 fox 4 brown 3 quick 2 w 23 r 18 a 1 x 24 d 4 j 10 y 25 u 21 k 11 h 8 g 7 f 6 t 20 i 9 e 5 n 14 v 22 m 13 s 19 l 12 c 3 p 16 q 17 b 2 z 26 o 15

    What you do is assign the returned hashref to (localised) glob. You can then access the has via that glob name using standard hash variable syntax instead hashref syntax. It does simplify the syntax without the need to copy and avoiding the risks of global vars.

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://332938]
Approved by halley
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (6)
As of 2019-10-18 18:47 GMT
Find Nodes?
    Voting Booth?