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

I'm trying to return a hash of arrays from a module. I think I'm creating the hash correctly, but if I try to return it, I get a reference to an empty hash. What should I be doing?
open(FMT, "./formats/$filters_file") || die "Can't open $filters_f +ile.\n"; while(<FMT>) { chomp; next if /^\*/; #comments line $var_name = substr($_,2,5); $var = substr($_,53); $var =~ s/\s+$//g; $var_name =~ s/(\$)|(\s+$)//g; if ( exists $filters{$var_name} ) { push @{ $filters{$var_name} }, $var; } else { $filters{$var_name} = [ $var ]; } } close FMT; return %filters;

Replies are listed 'Best First'.
Re: returning nested data structures
by suaveant (Parson) on Dec 22, 2009 at 21:13 UTC
    Well, not all of your code is here, so its hard to tell, but if you mean to return the hash as a reference you need a return \%filters;, if not you need to do %hash = Module::method(); since you will be returning as a list. But more importantly, are you sure there is any data in the hash at the end? Use some print statements or even better change return %filters to:
    use Data::Dumper; print STDERR Dumper(\%filters); return %filters;
    To make sure you actually have data!

                    - Ant
                    - Some of my best work - (1 2 3)

Re: returning nested data structures
by toolic (Bishop) on Dec 22, 2009 at 21:15 UTC
    When you say 'module', do you really mean 'sub'? If so, you should show how you are calling your sub. This is a way to return a hash-of-arrays from a sub:
    use strict; use warnings; my %filt = foo(); use Data::Dumper; print Dumper(\%filt); sub foo { # Create a hash-of-arrays my %filters = ( a => [0..2], b => [3..5] ); return %filters; } __END__ $VAR1 = { 'a' => [ 0, 1, 2 ], 'b' => [ 3, 4, 5 ] };
    You could also return it as a reference to a HoA.
Re: returning nested data structures
by jethro (Monsignor) on Dec 22, 2009 at 21:17 UTC
    What you may not know about the return function is that it evaluates its parameter(s) in the context of the subroutine invocation.

    If you called the subroutine like this: $f= sub(...) then %filters will be evaluated in a scalar context and return a string that shows some statistics of the hash, but no values of the hash itself.

    To rectify this you can do one of two things: Return a reference to the hash instead of the hash, i.e. "return \%filters;". Or change the call context, i.e. "%f= sub(...)". The second method copies the complete hash and should be avoided if the hash is really big

Re: returning nested data structures
by fzellinger (Acolyte) on Dec 22, 2009 at 21:17 UTC
    Try returning a reference to the hash:
    return \%filters;
    Other things to do:
  • Begin your code with:
    use strict;
  • Initialize filters:
    my %filters=();
  • Add some print statements.
  • Dump %filters prior to returning it just to check:
    use Data Dumper; print Dumper(\%filters);
Re: returning nested data structures
by brp4h (Acolyte) on Dec 22, 2009 at 21:45 UTC
    Sorry - I tried returning \%filters first, but that didn't work. The code I posted is in a sub within a module, because I need to use it in several programs. Here's what I'm doing in the main program (when returning \%filters):
    my($filters_ref) = GetFilters($filters_file); %filters = %$filters_ref; print \%filters; foreach (keys %filters) { print; }
    I get a hash reference with the first print line but nothing with the second. I've tested the data in the hash and it's perfectly correct before I return it.

      1) Can you print Dumper(\%filters) and check whether its reference of reference.

      2) Otherwise, try foreach (keys %{$filters_ref}) { print; } and see it works