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

I've never had reason to question where or how I use sort/reverse until now. Given the following code (note I'm doing string sorting):
my @keys = qw( 3242_38 2313_44 3242_37 3518_38 3242_49 3518_44 ); map { print "$_\n" } reverse @keys;
I would expect the following results:
3518_44 3518_38 3242_49 3242_38 3242_37 2313_44
But instead I get:
3518_44 3242_49 3518_38 3242_37 2313_44 3242_38
Which is neither sorted forward or reverse or the original order. If I change 'reverse' to 'sort' I get perfectly good sorted output. So why does 'reverse' put the wammy on my results? I must be missing something incredably simple here :(

UPDATE - If it was a snake it would have bit me. Excuse me while I go whack my head with a board for a few hours...

Replies are listed 'Best First'.
Re: sort/reverse strangeness
by moritz (Cardinal) on Oct 29, 2007 at 17:24 UTC
    You get exactly what you write, that is the reversed list.

    If you want to sort and reverse, you have to write both:

    for (reverse sort @keys){ print "$_\n" };

      Of course it's probably going to be more efficient to get the sorting order to reverse than to physically reverse the sorted list after the sort.

      for ( sort { $b cmp $a } @keys ) { print "$_\n"; }

      Update: Oooh, that's good to know. Never mind me then.

        reverse sort is optimized to do the reversing in sort itself, so any difference in speed should be very minor.

        Update: Corroboration:

        >perl -MO=Concise -e"@b = sort @a" ... 7 <@> sort lK ->8 ... >perl -MO=Concise -e"@b = reverse sort @a" ... 7 <@> sort lK/REV ->8 ...

        Update: It turns out that sort simply reverses the array at the end. But because it does so in-place without creating any stack frame, it's faster than reverse.

        if (PL_op->op_private & OPpSORT_REVERSE) { SV **p = sorting_av ? AvARRAY(av) : ORIGMARK+1; SV **q = p+max-1; while (p < q) { SV *tmp = *p; *p++ = *q; *q-- = tmp; } }
        Note that there is a difference between reverse sort LIST and sort { $b cmp $a } LIST; both are optimized, but the latter is stable (leaves elements in their original order) in the case of distinct elements with the same string value (overloaded, or dual valued), while the former is, err, reversed. Note which elements have a cached numeric value of 0 (and so don't warn in numeric context) here:
        $ perl use strict; use warnings; my @blanks = ("",""); { no warnings; $blanks[0]+0 } my @stable = sort { $b cmp $a } @blanks; my @reversed = reverse sort @blanks; warn '$stable[0]'."\n"; 1 if $stable[0]+0; warn '$stable[1]'."\n"; 1 if $stable[1]+0; warn '$reversed[0]'."\n"; 1 if $reversed[0]+0; warn '$reversed[1]'."\n"; 1 if $reversed[1]+0; __END__ $stable[0] $stable[1] Argument "" isn't numeric in addition (+) at - line 10. $reversed[0] Argument "" isn't numeric in addition (+) at - line 12. $reversed[1]
        Sort comparisons of { $a <=> $b } and { $b <=> $a } (with or without reverse) are also optimized.
Re: sort/reverse strangeness
by Anonymous Monk on Oct 29, 2007 at 17:24 UTC

    Please read the docs for reverse again. reverse doesn't sort in reverse order. It just reverses order. Perhaps you want reverse sort LIST?

    - ikegami with net problems.