Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should you NOT return an array ref?

In the question "Is returning a whole array from a Perl subroutine inefficient" two people recommend against optimizing if there is no need for it. As a general rule, optimizing can add complexity, and if it's not needed, simple is better. But in this specific case, returning an array versus an array ref, I don't see that there's any added complexity, and I think consistency in the interface design would be more important. Consequently, I almost always do something like:

sub foo
{
   my($result) = [];

   #....build up the result array ref

   $result;
}

Is there a reason I should not do this, even for small results?

like image 278
Joe Casadonte Avatar asked Feb 15 '09 13:02

Joe Casadonte


2 Answers

Since nobody mentioned about wantarray, I will :-)

I consider a good practice to let the caller decide what context it wants the result. For instance, in the code below, you ask perl for the context the subroutine was called and decide what to return.

sub get_things {
    my @things;
    ... # populate things
    return wantarray ? @things : \@things;
}

Then

for my $thing ( get_things() ) {
    ...
}

and

my @things = get_things();

works properly because of the list context, and:

my $things = get_things();

will return the array's reference.

For more info about wantarray you might want to check perldoc -f wantarray.

Edit: I over-sighted one of the first answers, which mentioned wantarray, but I think this is answer is still valid because it makes it a bit clearer.

like image 110
Igor Avatar answered Sep 19 '22 12:09

Igor


No. Except do "return $result;" for clarity.

I remember testing the efficiency of those, and the difference in performance was minimal for small arrays. For large arrays, returning a reference was way faster.

It's really a convenience thing for small result. Would you rather do this:

($foo,$bar) = barbaz();

Or returning a reference:

 $foobar = barbaz();
 $foobar->[0]; # $foo
 $foobar->[1]; # $bar

Another way to return a reference:

($foo,$bar) = @{barbaz()};

As a rule, once you decide which way to go, just keep to it for you module, since it makes it confusing to switch from one method to the next.

I typically return array references for lists of similar things, and an array when the response is composed of two to four different elements. More than that, I make a hash, since not all caller will care about all the response elements.

like image 38
Mathieu Longtin Avatar answered Sep 21 '22 12:09

Mathieu Longtin