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

From the sort documentation: "Do not declare $a and $b as lexical variables (with my). They are package globals."

WHY? This is suddenly very frustating. Maybe some one here can help me get around this problem. I have a set of strings with a prefered sort order. So I wrote a hash associating each string to it's position in the sort order, and then a sub SortByMyOrder method to do the look ups. It gets used in lots o' places, so I moved it into a small package. But now it doesn't work any where because $a and $b are not in the right package. I could solve this with eval and caller, but I don't want to do that because qsort could potentially make lots o' calls into this method. How can I tell Perl to get the $a and $b scopes correct?

Replies are listed 'Best First'.
Re: package globals and sort()
by tachyon (Chancellor) on Apr 19, 2002 at 00:39 UTC

    Eh? You will need to post code because it has nothing to do with $a and $b being in one package or another. You can see this example works fine.

    You can declare a my $a or my $b in package main but not in package Sort as these vars need to be package globals there for sort() to work.

    package Sort; # my($a,$b); # <<-- can't do that in this package sub my_num_sort { my $list_ref = shift; # return as a list ref for efficiency return [sort { $b <=> $a } @$list_ref]; } package main; # my($a,$b); # <<-- you can do this in this package (no sorts) my @list = ( 10, 42, 66, 1, 81, 32 ); # pass and return as a list ref for efficiency my $sorted = Sort::my_num_sort(\@list); print "$_ " for @$sorted;

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Ah. Sorry. The method doesn't actually do the sort (too much copying for my tastes). It just defines the sort rules. Something like:
      package MyOrder; use strict; # export junk goes here... my %order = ( # order hash goes here... ); sub SortMyWay { if ( exists $order{$a} and exists $order{$b} ) { return $order{$a} <=> $order{$b} } elsif ( exists $order{$a} ) { return 1 } elsif ( exists $order{$b} ) { return -1 } else { return $a cmp $b } } package main; use strict; # use the module with the sort stuff in it, # which also exports sub SortMyWay my @foo = ( # stuff to sort goes here... ); my @bar = sort SortMyWay @foo;
      and of course I get an error. sigh. I wonder if AUTOLOAD could do it. I never used that before...

        Just do the actual sort in the MyOrder Package as shown. Note as we pass list references we pass 4 bytes in and 4 bytes out of the MyOrder package.

        package MyOrder; my %order = ( ); sub SortCriteria { if ( exists $order{$a} and exists $order{$b} ) { return $order{$a} <=> $order{$b} } elsif ( exists $order{$a} ) { return 1 } elsif ( exists $order{$b} ) { return -1 } else { return $a cmp $b } } sub SortMyWay { my $list_ref = shift; return [sort SortCriteria @$list_ref]; } package main; use strict; my @foo = qw( j a p h , ); my $bar = MyOrder::SortMyWay(\@foo); my @bar = @$bar; print "@bar";

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: package globals and sort()
by japhy (Canon) on Apr 19, 2002 at 02:50 UTC
    Check out my Resorting to Sorting. It'll help you figure out what to do.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a (from-home) job
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;