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__