Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

my $a outside sort block incompatibility

by Anonymous Monk
on Feb 20, 2009 at 23:49 UTC ( [id://745469]=perlquestion: print w/replies, xml ) Need Help??

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

Hi. Is there a way of getting the following to work (e.g., some kind of local declaration) -- outside of using a different name for "my $a"? Thanks.
my @arr1 = (1, 3, 5, 2, 4, 6); my @arr2; # Works as expected. @arr2 = sort { $a <=> $b } @arr1; print join(' ', @arr2), "\n"; # Gives: Can't use "my $a" in sort comparison at ./sort_a.pl line 12. my $a = 'whatever'; # just happens to be in scope of below sort block @arr2 = sort { $a <=> $b } @arr1; print join(' ', @arr2), "\n";
I thought I'd previously found a way of using "local" to get around this but I can't reconstruct it now.

Replies are listed 'Best First'.
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
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.
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.
      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";
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.
Re: my $a outside sort block incompatibility
by Your Mother (Archbishop) on Feb 21, 2009 at 00:03 UTC

    Would something like this be easier and less (potentially) misleading...?

    my $moo = 3; @arr2 = sort { $moo <=> $b } @arr1;
      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.
        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.

Re: my $a outside sort block incompatibility
by BrowserUk (Patriarch) on Feb 21, 2009 at 03:49 UTC
      That only works if you are calling sort from package main.

        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.
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

    'Ebry haffa hoe hab im tik a bush'. Jamaican proverb

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://745469]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2024-04-24 00:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found