Re: my $a outside sort block incompatibility
by GrandFather (Saint) on Feb 21, 2009 at 01:41 UTC
|
Don't do that! Using single character identifiers is generally frowned on. Using 'special' single character identifiers is simply asking for trouble (as you have found). In most cases more explicit identifiers make code easier to maintain and avoid a range of traps. It may be appropriate to use $paramA or $aTerm for example
True laziness is hard work
| [reply] |
Re: my $a outside sort block incompatibility
by toolic (Bishop) on Feb 21, 2009 at 02:46 UTC
|
Even more documentation telling you to avoid this scenario from sort:
If you're using strict, you must not declare $a and $b as lexicals. They are package globals.
etc. | [reply] |
Re: my $a outside sort block incompatibility
by hbm (Hermit) on Feb 21, 2009 at 00:11 UTC
|
I assume you want to declare $a beforehand but not use its value in sort. If that is the case, you could declare a local sub before $a:
local *_sort = sub { return sort { $a <=> $b } @_ };
my $a = 'whatever';
print join(' ', &_sort(@arr2)), "\n";
But obviously it would be easier to just use a different variable name...
Update: I just read up on $a and $b in perlvar:
Special package variables when using sort(), see sort. Because of this specialness $a and $b don't need to be declared (using use vars, or our()) even when using the strict 'vars' pragma. Don't lexicalize them with my $a or my $b if you want to be able to use them in the sort() comparison block or function. | [reply] [d/l] |
|
D'oh! Reading your comment reminded me of the solution--using "our"--that I had found earlier but misremembered as using "local". Thanks much.
# Works.
my $a = 'whatever'; # just happens to be in scope of below sort block
@arr2 = sort { our $a; $a <=> $b } @arr1;
print join(' ', @arr2), "\n";
| [reply] [d/l] |
Re: my $a outside sort block incompatibility
by tilly (Archbishop) on Feb 21, 2009 at 08:51 UTC
|
Yet another way to do it is to use a sort routine with a ($$) prototype on it.
...
my $a = "whatever";
my $sort_sub = sub ($$) { $_[0] <=> $_[1] };
@arr2 = sort $sort_sub @arr1;
...
The main reason to use the ($$) prototype in a sort routine is the case where you may be defining the sort routine in one package, and then calling sort in another. | [reply] [d/l] |
Re: my $a outside sort block incompatibility
by Your Mother (Archbishop) on Feb 21, 2009 at 00:03 UTC
|
my $moo = 3;
@arr2 = sort { $moo <=> $b } @arr1;
| [reply] [d/l] |
|
Thanks for replying. I guess I wasn't clear enough. Actually, the two $a variables are supposed to be unrelated. The "my $a" is hypothetically a reasonably appropriate name chosen for the variable given its meaning, but it happens to conflict with perl's use of global $a.
| [reply] |
|
I have significant difficulty in accepting that hypothesis.
$i/$j/(occasionally) $k are sufficiently widely-used and well-known that they are acceptable as loop counters. $x/$y/$z are appropriate for geometric coordinates, again due to long and widespread use.
Offhand, I can think of no other cases in which a single-character variable name is "reasonably appropriate", regardless of whether it happens to conflict with a magical name built into the language or not.
| [reply] |
|
|
Re: my $a outside sort block incompatibility
by BrowserUk (Patriarch) on Feb 21, 2009 at 03:49 UTC
|
my $a = 'whatever';
@arr2 = sort { $::a <=> $::b } @arr1;
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
That only works if you are calling sort from package main.
| [reply] |
|
Of course you need to use the appropriate package variables. That said, I recind my suggestion in favour of the OPs use of our.
Not because of any problem with the use of qualified package vars, but because against my expectations, it runs far more quickly. Indeed, unless someone can show me the flaw in my benchmark, I'll be explicitly including our( $a, $b) in all my sorts from now on:
#! perl -slw
use strict;
use Benchmark qw[ cmpthese ];
cmpthese -10, {
"\$a<=>\$b" => q[my @a = sort{ $b <=> $a } 1
+.. 1e6;],
"\$::a<=>\$::b" => q[my @a = sort{ $::b <=> $::a } 1
+.. 1e6;],
"our(\$a,\$b)" => q[my @a = sort{ our( $a, $b ); $b <=> $a } 1
+.. 1e6;],
};
__END__
C:\test>junk2.pl
s/iter $::a<=>$::b $a<=>$b our($a,$b)
$::a<=>$::b 2.09 -- -0% -77%
$a<=>$b 2.08 0% -- -77%
our($a,$b) 0.469 344% 343% --
UPDATE: I guess it really is time to upgrade. Under 5.10 I get much closer to what I expected:
Rate our($a,$b) $a<=>$b $::a<=>$::b
our($a,$b) 1.75/s -- -46% -46%
$a<=>$b 3.24/s 85% -- -0%
$::a<=>$::b 3.24/s 86% 0% --
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
|
Re: my $a outside sort block incompatibility
by poolpi (Hermit) on Feb 23, 2009 at 15:03 UTC
|
I thought I'd previously found a way of using "local" to get around this but I can't reconstruct it now.
#!/usr/bin/perl
use strict;
use warnings;
my @arr1 = ( 1, 3, 5, 2, 4, 6 );
my @arr2;
local $a = 'whatever';
{
@arr2 = sort { $a <=> $b } @arr1;
}
print join( ' ', @arr2 ), "\n";
hth, PooLpi
| [reply] [d/l] |