in reply to Sort and related stuff

Disclaimer: I have not looked into the Perl internals of sorting, so this is based just on my naive observations.

The method of using $test = $a || shift is an interesting way to implement a dual-use function, but you get bitten by Perl magic as you see.

In the first case, Perl rightfully complains about the variables $a and $b only being used once, since that is what you effectively do.

In the second case, deep Perl (optimization) magic is at work, since the variables $a and $b get filled with sort parameters for speed reasons and thus get "used" as far as Perl (or rather, the warnings-part of perl) is concerned. So, for sorting, $a and $b have been declared globally by the sort magic, and then warnings finds them already used (and maybe even declared) and thus shuts up.

I don't see any good solution to your dilemma, as the two or three approaches I see only lead down to beaten but bad paths :

#!/usr/bin/perl -w use strict; my ($a, $b); # Bad bad bad thing ! ($a, $b) = ( "5","6" ); sub mySort { return ($a||shift) cmp ($b||shift); }; print "\n1: ", mySort( "1","2" ); print "\n2: ", join " ", sort qw!d b c a!; print "\n3: ", mySort( "8","7" ), "\n"; print "\n\$a: $a, \$b : $b\n";
This code prints, when run
G:\>perl -w test.pl 1: -1 2: a b c d 3: -1 $a: 5, $b : 6
Here, the cases 1 and 2 are pretty sane, and as you see, even the my-declared variables $a and $b didn't get clobbered. But (and there's always a "but") case 3 is a very nice case of how to hide errors in interesting and nonobvious ways. If not called explicitly via sort, the routine now accesses the my-declared variables $a and $b, which have been initialized (by a stupid user understanding none of the code) to (5,6), which messes up all subsequent compares. So this is a really bad idea, because you can't make sure that noone initializes your "protectively" predeclared variables...

I'm not sure that there is no perlish idiom for handling such cases, but I haven't seen them yet :-)

Replies are listed 'Best First'.
Re: Re: Sort and related stuff
by leons (Pilgrim) on Feb 23, 2001 at 15:58 UTC
    Hi,

    Thanks a lot for your help ! I just tried the solution Tyke
    came up with. And it seems like a pretty good one (use vars qw/$a $b/;)
    I tried it and it works perfectly and I haven't been able to
    create a situation in which it doesn't work. So I think I'll go for
    this one.

    Thank you all for thinking along with me ! ;-)

    And now for some lunch ! Bye, Leon

      This solution has the same problems as my my-predeclare solution has. If somebody is stupid enough to assign something to $a and $b, then this method won't work for the single-call case. But on the other side, the single-call case will never work, if somebody actually uses variables called $a and $b in any way other than within a sort-callback.

        No. Your my-declaration had the problem that you changed $a and $b to lexical variables, so when the sort function was setting the globals $a and $b, the function looked at the wrong variables.

        Let us not mention the fact that your example assumed that the data never would include false values...