At 3:43 PM -0600 1/27/01, Ken Williams wrote:
>[EMAIL PROTECTED] (Vic Norton) wrote:
>>Thanks Bruce Van Allen and Ken Williams!
>>
>>I've just implemented Bruce's suggestion:
>>
>>     sub naturalorder {
>>     # A subroutine that sorts like the Macintosh Natural Order extension.
>>     # Created by Vic Norton, 26 Nov 2000.
>>     # Modified to work in an external package on 27 Jan 2001;
>>     # Thanks to Bruce Van Allen <[EMAIL PROTECTED]>.
>>
>>     # Bruce Van Allen's modification
>>         my ($pkg) = caller;
>>         no strict 'refs';
>>         my $a = ${$pkg.'::a'};
>>         my $b = ${$pkg.'::b'};
>>
>>     # Norton's original routine continues from here
>>         my $u = lc($a);
>>         my $v = lc($b);
>>         ...
>>     }
>>
>
>Hi Vic,
>
>It sounds like this solution works well for you in this case, but for
>larger or more oft-sorted arrays the overhead of calling 'caller' each
>time might get sluggish.  So hang on to the other methods for the future
>as well.

Ken's point is important. The approach I described would benefit from 
taking the statement

   my ($pkg) = caller;

out of the subroutine definitions. Place it before the subs are 
defined in the module. To optimize further, turning off strict 'refs' 
could also be done module-wide.

This not only reduces code bytage and avoids piercing the module 
shell, but also gains hugely in performance with large sorts. 
caller() is called once for the entire time in which the external 
module (Sorts.pm in the above) is 'use'ed in this package. If the 
module is 'use'ed in another package, caller() will be called 
freshly, once, for  all the times that the module's methods will be 
used in that package.

package Sorts;

my ($pkg) = caller;
my $xa = $pkg.'::a';
my $xb = $pkg.'::b';

no strict 'refs';

sub case_order {
   my $a = ${$xa};
   my $b = ${$xb};
   $a cmp $b
}

# For simple sorts, lose the variables.
sub not_case_order {
   lc(${$pkg.'::a'}) cmp lc(${$pkg.'::b'})
}
1;
__END__


If a variable has been defined earlier in the same scope in which the 
subroutines are defined, the value in the variable at that time is 
accessible to the subroutines when they are used later. $xa and $xb 
hold the compound names, e.g., package_name::a and package_name::b, 
which when surrounded by ${ ... } within the sort subroutines become 
the magical $a and $b sorting variables.

Remember that anything you do to change $a and $b during a sort 
changes the real thing, which one rarely wants to do. So if you 
change ${$xa} or ${$pkg.'::a'}, you are changing 'real' $a, the value 
of the item in the list being sorted. To prevent this, the case_order 
sub in the script above begins with

   my $a = ${$xa};

Within the sub, $a gets the value of the 'real' sorting $a, but any 
change to the sub's $a won't affect real $a. This is a benefit in 
some sort subroutines:

sub rev_case_order {
   my $a = ${$xa};
   my $b = ${$xb};
   $a =~ tr/[A-Z][a-z]/[a-z][A-Z]/;
   $b =~ tr/[A-Z][a-z]/[a-z][A-Z]/;
   $a cmp $b
}

Anyway, thanks, Ken. What else? I think you know more about this than I do...

1;


-- 

   - Bruce

__bruce_van_allen__santa_cruz_ca__

Reply via email to