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

If I want to return a reference to the results of a sort, I am guessing I can do this:
my @sorted = sort @stuff; return \@sorted;
...And when @sorted goes out of scope, I'll have returned a reference to an anonymous array - but that is so ugly! Is there a quick and lovely way to write it in a single expression?

Replies are listed 'Best First'.
Re: Reference to sort results
by FunkyMonk (Bishop) on Aug 05, 2009 at 12:04 UTC
Re: Reference to sort results
by Marshall (Canon) on Aug 05, 2009 at 12:18 UTC
    Whoa! my @sorted = sort @stuff; is right and easy. Where does this return \@sorted come from? Also possible is @stuff = sort @stuff;

    Yes, it is possible to pass a reference to an array to be sorted like below, but why bother? You have a one line thing that sorts "stuff".

    #!/usr/bin/perl -w use strict; my @a = (4,5,1,2); print "@a\n"; sort_ref_2_array (\@a); print "@a\n"; sub sort_ref_2_array { my $aref = shift; @$aref = sort @$aref; } __END__ prints: 4 5 1 2 1 2 4 5
      Why bother? ...Because in reality I have an object containing a large hash, and I want one of its methods to return a sorted list of its values. More like:
      @sorted = sort { $a->{VAL} <=> $b->{VAL} } keys %bigHash; return \@sorted;
      Surely it is more efficient to return a reference to that list, as returning the array itself will involve creating a new copy of that array. If I use:
      return [ sort { $a->{VAL} <=> $b->{VAL} } keys %bigHash ];
      Will that duplicate the array, or just return a reference to the extant array? It isn't clear what perl does internally with this stuff. I'm just trying to be efficient, rather than throwing around big arrays willy-nilly.
        It's a reference to an anonymous array which is created in the same step as the return statement. Why would it duplicate it?

        Going from right to left:
        keys %bigHash
        generates a list, containing the values in the hash.
        sort {...}
        Manipulates the list according to the sort rule (sorts in ascending numerical order of the value associated with the key). Still a list.
        [...] #now the brackets
        the brackets tell Perl that "hey, this list in here? gimme a ref to an array with those elements in that order. This is the first point where it's an array in your example. It's unclear where you think copying an array is occurring. There's no practical difference between
        my @foo=sort @bar; return \@foo;
        and
        my $foo=[sort @bar]; return $foo;
        unless you try to manipulate the array in the subroutine, in which case you'd need to deal with @$foo in the second example. sort operates on a list and returns a list. If you use an array to feed it, it doesn't change the original array. The array you're worried about copying isn't an array yet at that point, so there's no risk of copying it.

        (And as a general note, if you aren't observing what appears to be a resource-driven slowdown, you should usually not try to out-think the language implementation, because in certain circumstances you can interfere with compiler-level optimization)

        Edit: I think perlreftut might provide some enlightenment.
      Sorry: where I wrote "keys", I meant "values".
Re: Reference to sort results
by Anonymous Monk on Aug 05, 2009 at 12:05 UTC
    Why is it ugly?
    return [ sort @stuff ]
      This is "ugly" because if you pass me a ref to an array to be sorted, there will be NO return value. The array has been sorted when I return. The sub just does the sort and that's it. I replied at the wrong level. Ooops. Sorry if I offended.