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

I'm having a devil of a time w/ perlref and perlsub... The goal is to return a list that is generated in a subroutine. I'm passing a hash and an array from another subroutine. The array and hash that I pass in are fine and do the right thing. something like this:
sub blah { match_files(\@array, \%hash); } sub match_files { # do stuff to compare array against hash push(@files, $array_element); # add some ary elements return @files; }
I've tried:
@returned_files = match_files(\@array, \%hash);
and
match_files(\@array, \%hash); print "@files\n";
and
$returned_files = match_files(\@array, \%hash); print "$@returned_files \n";
it shouldn't be this hard. any pointers in the right direction would be very much appreciated. -v

Replies are listed 'Best First'.
•Re: subroutines and returning lists...
by merlyn (Sage) on Apr 03, 2003 at 22:33 UTC
      Merlyn & Dmitri: Thank you for your assistance. I had some print statements in the subroutine, so I know that the actual matching of array against hash does work and $ary_element is a defined value before I try to push it. Here is what I'm doing with @_ (this still doesn't work):
      sub blah { @array = match_files(\@array, \%hash); print "@array \n"; } sub match_files { @files = (); my($array, $hash) = @_; my(@array) = @$array; my(%hash) = %$hash; foreach $ary_element (@array) { foreach $hash_key( keys ( %hash )) { # do my comparison here } # if i get a match print "$ary_element\n"; # prints defined value push (@files, $ary_element); return @files; } }
        Your problem is that you try to return multiple times (every loop through the first foreach). This means that you end up returning an array with only one element. Put the return statement just before the end of the sub (after the foreach).

        Added clarification.

        The Mad Hatter has already pointed out the problem. Also it is better to return array ref instead of array. By doing that, you will gain much better performance. If you return array, Perl needs to duplicate the entire array, and that takes time.

Re: subroutines and returning lists...
by MrYoya (Monk) on Apr 03, 2003 at 22:39 UTC
    Your first example, with
    @returned_files = match_files(\@array, \%hash);
    looks like it should work.

    Also, to dereference an array reference, try @$returned_files

    Compare these examples. The first returns a reference to an array:

    #!/usr/bin/perl -w use strict; sub ret_array { my @array = qw( 1 2 3 4 5 ); return \@array; } my $returned_array = ret_array(); print @$returned_array;

    And this returns an array
    #!/usr/bin/perl -w use strict; sub ret_array { my @array = qw( 1 2 3 4 5 ); return @array; } my @returned_array = ret_array(); print @returned_array;
Re: subroutines and returning lists...
by The Mad Hatter (Priest) on Apr 03, 2003 at 22:40 UTC
    You should just be able to set an array equal to the return value of the subroutine (like you did in your first try). Are you sure the code isn't working somewhere else? What is the error you're getting or what specifically isn't working?

    This works for me:

    sub t { @file = ('foo', 'moo', 'bar'); return @file; } @tmp = t(); print @tmp; # print t(); would also work...
    and outputs foomoobar like expected.
Re: subroutines and returning lists...
by dmitri (Priest) on Apr 03, 2003 at 22:33 UTC
    @returned_files = match_files(\@array, \%hash);

    should do fine, if the last statement in match_files() is indeed return @files. Are you sure match_files() does not return before that? Also, if @files is empty, the function will return an empty list. Try manually adding an element to that array to make sure that it indeed returns something.

Re: subroutines and returning lists...
by jobber (Sexton) on Apr 03, 2003 at 22:35 UTC
    Hello, Look at the below code, it returns an array from a sub.
    @array = ("hi","hello"); @final_array = match_files(\@array); sub match_files { push(@files, "hola", @array); return @files; } for (@final_array) { print; }
    Your problem is you are storing the results of the sub which are an array into a scalar varialble.