in reply to Returning two arrays..

Why not make an @array of arrays, and return that array. This way you need restricted to two arrays. So,
push(@allarrays,\@array1); push(@allarrays,\@array2); return \@allarrys;

Replies are listed 'Best First'.
Re: Re: Returning two arrays..
by mr_mischief (Monsignor) on Jan 04, 2002 at 07:36 UTC
    This is a good suggestion, and you're on the right track, but I was wondering why you return a reference to the main array. The only ones you really need to make references to are the second level deep. There's not really any need to use more references than will get the job done comfortably.

    I really do like the suggestion to return an array of array references, though, instead of just returning two array references. Either way would work the same from outside the sub, though.
    sub f { @foo = ( 1, 2 ); @bar = ( 3, 4 ); @all = ( \@foo, \@bar ); return @all; } foreach ( f() ) { print @{$_}; }
    isn't much different from returning two references:
    sub f { @foo = ( 1, 2 ); @bar = ( 3, 4 ); return \@foo, \@bar; } foreach ( f() ) { print @{$_}; }
      I am sure this will be subject to debate, but I have learned that it is more efficent to return a reference then the whole thing.

      For example, if you array is a million elements and you a million arrays, then that is alot to pass around. The size of that versus the size of one scalar (the reference) is obviously very different. Because of this, I have gotten in the habit of returning references to data structures, especially complex ones such as arrays or arrays.

        Beware of micro-optimizations, as they depend on non-obvious factors. At best, it's a wash. In a situation like this, I suspect it's actually less efficient to create a new array, push two references on it, take a reference to it, create a (single element) list, and return the list. The other alternative is to create a two element list and return that.

        Sure, there's one more element to push on the return stack and one more element to copy, if the caller uses the returned list, but you'll have to copy something in both cases, and if you return a reference to an array of references, you'll have to go through more levels of dereferencing.

        I don't know where it's more efficient to do it your way, but it probably doesn't converge until you're returning at least five or six references.

      I believe that
      @all = (\@foo, \@bar); return @all;
      and
      return \@foo, \@bar;
      are identical so far as perl is concerned. Kind of like
      print (1, 2, 3, 4); # and print 1, 2, 3, 4;

      Anyway my suggestion is that if you're expecting a set number of elements from a subroutine then you can do something like this:

      my ($aryref1, $aryref2) = subroutine(); # or if you want the longer way. my $aryref1; my $aryref2; ($aryref1, $aryref2) = subroutine();
      Note that if a subroutine returns a list and you do something like:
      my $ret = subroutine();
      Then $ret will be the number of elements in the list that subroutine returned, not the first.

      Jacinta

        The difference is you can't push onto a returned list. If you've many references to return or don't know how many you need to return at compile time, then an array will be much more handy. I just pointed out that for something this simple it does the same from outside the sub. That doesn't mean they'll each scale as well as the other.