On Wed, Jul 25, 2001 at 05:05:03PM -0700, Randal L. Schwartz wrote:
> For this to work, the element indirected by $a would have to always be
> to the left of the element indirected by $b, and that's probably not
> true.  In fact, we can see this:

I noticed that in a few of my tests and never really connected why
this happens.   Thanks Randal.

So I decided to make a quick experimental hack on perl's source and
change sortcv_stacked a bit.  (C source at the end of this message, 
changes indicated in /**/'s).  This is the comparison function that gets
called when you have a prototyped sort function.

So now when you have a prototyped sortsub:

        sub foo ($$) {
        }

The third argument passed is the relative position of the two 
comparison values either 1 or -1.  So here's the new sort function:

sub foo ($$) {
        if ($_[0] < $_[1] and $_[2] > 1) {
                ($_[0],$_[1])=($_[1],$_[0]);
        }
}

And calling it with:

        for(0..20) { push(@r, int rand(50)) }
        @s=sort foo @r;

Yeilds an @r that's properly re-ordered!  An in-place sort?  At least
that's what I thought when I said:

        print join(',', @s), "\n";
        print join(',', @r), "\n";

I got the correct results.  Now the problem is that even though this
appears to work -- it doesn't.  Saying:

        for(0..20) { push(@r, int rand(50)) }
        @s=sort foo @r;
        print join(',', @r), "\n";  # Prints sorted
        @s=();
        print join(',', @r), "\n";  # Prints unsorted!

Yeilds the original unsorted list.  WTF?  It's as though the elements
of @r were masked by the elements of @s.  It's not the patch.  Without
the patch, the "Prints sorted" line above just "Prints in weird order".

*scratching head*

Maybe this is why no-one's really looked at modifying $a and $b 
within a sortsub.  :)

If someone can explain *this* to me, I could probably finish a patch
for in-place sorting in Perl.   But I'm lost as to why (or HOW) @r
can be "unwound" like this well after the fact.

-------------
C Source change from pp_ctl.c, sortcv_stacked().  I'm out of practice
hacking C, and the Perl source mystifies me most of the time.  5.7.0

    if (AvMAX(av) < 2) {  /* Was 1 */
        SV** ary = AvALLOC(av);
        if (AvARRAY(av) != ary) {
            AvMAX(av) += AvARRAY(av) - AvALLOC(av);
            SvPVX(av) = (char*)ary;
        }
        if (AvMAX(av) < 2) {  /* was 1 */
            AvMAX(av) = 2;    /* was 1 */
            Renew(ary,3,SV*); /* was 2 */
            SvPVX(av) = (char*)ary;
        }
    }
    AvFILLp(av) = 2;  /* was 1 */

    AvARRAY(av)[0] = a;
    AvARRAY(av)[1] = b;
    AvARRAY(av)[2] = newSViv(a>b?1:-1); /* Relative positions */


-- 
    Clinton A. Pierce            Teach Yourself Perl in 24 Hours  *and*
  [EMAIL PROTECTED]                Perl Developer's Dictionary
"If you rush a Miracle Man,     for details, see http://geeksalad.org     
        you get rotten Miracles." --Miracle Max, The Princess Bride

Reply via email to