Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

returning a hash from a module

by jms53 (Monk)
on Feb 28, 2013 at 18:56 UTC ( #1021092=perlquestion: print w/replies, xml ) Need Help??
jms53 has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,
I have a module that gets information from a database, and has a sub that returns a hash.
sub get_transactions { my $transactions_id = shift; my $sql = <<EOSQL # the sql part works EOSQL my $ar = $dbh->selectall_arrayref( $sql, undef, $transactions_id ); my %transactions; for ( @$ar ) { my ($date, $type, $amount, $new_balance) = @$_; %{$transactions{$date}} = ('Date' => $date, 'Type' => $type, 'Amou +nt' => $amount, 'Ending_balance' => $new_balance); } return %transactions; }

if Dumper is used on %transactions in the module, the correct information is printed to the terminal, however, when I try to do this on a script, I get no output:
my %transac = MyDB->get_transactions( 10000); print Dumper %transac;
which outputs nothing.I have tried using references,
#Module: ... return \%transactions; #script my $transac = MyDB->get_transactions( 10000); print Dumper $transac;

which output  $VAR1={}

I've managed to point the problem to how I'm calling the sub, but haven't managed tog et it to work as expected.
Thank you,

J -

Replies are listed 'Best First'.
Re: returning a hash from a module
by choroba (Bishop) on Feb 28, 2013 at 20:47 UTC
    The problem is you call the subroutine as a class method:
    Therefore, the first argument to the subroutine is not the id, but the class name. Insert the following line to the top of the sub:
    my $class = shift;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thanks! Now it's always returning something, although now it's an empty hash. Looks like I have some cleaning up to do in the module over the week end.
      J -
Re: returning a hash from a module
by blue_cowdawg (Monsignor) on Feb 28, 2013 at 20:18 UTC

    If you have a hash %some_hash and want to return it from anywhere you need to have a hash to put it in. Example:

    | hand waving here. my %reciever = get_stuff(); | more handwaving sub get_stuff { my %hash =(); # fill hash return %hash; }
    Now if you want to use a a hash reference
    my $reciever=get_stuff(); sub get_stuff { my %hash = (); # yada yada return \%hash;
    Clear as mud?

    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: returning a hash from a module
by kcott (Chancellor) on Feb 28, 2013 at 21:47 UTC

    G'day jms53,

    To use Data::Dumper to display a hash, you should probably be using a reference to the hash in question. Consider this which uses a hash:

    $ perl -Mstrict -Mwarnings -e ' use Data::Dumper; my %x = (a => 1); print Dumper %x; ' $VAR1 = 'a'; $VAR2 = 1;

    Now compare the output using a reference to the hash:

    $ perl -Mstrict -Mwarnings -e ' use Data::Dumper; my %x = (a => 1); print Dumper \%x; ' $VAR1 = { 'a' => 1 };

    Using $date as a key seems ill-advised. Are there ever more than a single transaction on any given day? If so, you'll be overwriting all transactions for that day with the last one from the result set. Aim for unique keys: perhaps a combination of date and a transaction ID.

    You're calling get_transactions() as MyDB->get_transactions(10000). I'll assume this is a class method with MyDB being the class. You could remove any ambiguity for Perl by writing MyDB::->get_transactions(10000); however, that's not your real problem here: the first argument to get_transactions() will be the class name and the second argument will be 10000, so your code for get_transactions() should look more like this:

    sub get_transactions { my ($class, $transaction_id) = @_; ... }

    Presumably, you're getting an empty result set because you don't have any transaction IDs called "MyDB". Adding a few basic debugging statements would have identified this issue for you rather quickly, e.g.

    ... my $transactions_id = shift; print "$transactions_id\n"; ... my $ar = $dbh->selectall_arrayref( $sql, undef, $transactions_id ) +; print Dumper $ar; ...

    I'd also take a look at $dbh which appears out of the blue in get_transactions(). It might be worth passing that in as another argument so you know exactly what database handle you're using rather than relying on a correct global variable being in scope.

    Finally, as a general rule-of-thumb, I'd always return a hashref, in preference to a hash, from a subroutine unless I had a very good reason not to. With a hashref, you're only returning a single scalar; a hash with the entire result set might contain hundreds, thousands or millions of scalars. And are you calling get_transactions() once or in a loop? [Use the same rule-of-thumb for returning an arrayref in preference to an array.]

    -- Ken


      I will try with the hash reference for Data::Dumper.

      My output seems to be changing each time I call it, so will have to try to fix this over the week end.

      $date is unique, as it includes both informations, as well as time. (However, I'm not interested in displaying the time).

      Thanks a lot for the input.
      J -
Re: returning a hash from a module
by sundialsvc4 (Abbot) on Mar 01, 2013 at 04:58 UTC

    Since the return-value from a sub must be “one single thing,” it should properly be a hash reference.

      Actually, return will return a list, scalar or void depending on the context of the expression after the return statement. So if you return a hash it will flatten it to a list. If there is an assignment of the return value into a hash then the list is put into the hash. Same with arrays.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1021092]
Approved by Old_Gray_Bear
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (5)
As of 2018-06-25 05:25 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (126 votes). Check out past polls.