Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl variable scope question

Tags:

scope

class

perl

So I have a Perl class. It has a sort() method, and I want it to be more or less identical to the built-in sort() function:

$object->sort(sub ($$) { $_[0] <=> $_[1] });

But I can't do:

$object->sort(sub { $a <=> $b });

Because of scoping. But the List::Util module does this with reduce(). I looked at the List::Util module, and they do some rather nasty things with no strict 'vars' to make this happen. I tried that, but to no avail.

It is my understanding that reduce() works the way it does because it is exported into the appropriate namespace, and thus my class can't do this since the function is quite firmly in another namespace. Is this correct, or is there some (undoubtedly more hideous and ill-advised) way to do this in my situation?

like image 704
Chris Lutz Avatar asked Aug 24 '09 23:08

Chris Lutz


People also ask

What is the default scope of Perl variable?

Strictly speaking, the default scoping of variables in Perl is the package global.

What does $_ mean in Perl?

There is a strange scalar variable called $_ in Perl, which is the default variable, or in other words the topic. In Perl, several functions and operators use this variable as a default, in case no parameter is explicitly used.

What is $$ in Perl?

$$ The process number of the perl running this script. (Mnemonic: same as shells.) $? The status returned by the last pipe close, backtick (\`\`) command or system operator.

What are the three categories of Perl variables?

Perl has three main variable types: scalars, arrays, and hashes.


1 Answers

Well, the other two answers are both half-right. Here's a working solution that actually sorts:

package Foo;

use strict;
use warnings;

sub sort {
    my ($self, $sub) = @_;

    my ($pkg) = caller;
    my @x = qw(1 6 39 2 5);
    print "@x\n";
    {
        no strict 'refs';
        @x = sort {
            local (${$pkg.'::a'}, ${$pkg.'::b'}) = ($a, $b);
            $sub->();
        } @x;
    }
    print "@x\n";

    return;
}


package main;

use strict;
use warnings;

my $foo = {};
bless $foo, 'Foo';

$foo->sort(sub { $a <=> $b });
# 1 6 39 2 5
# 1 2 5 6 39

Presumably you'd sort some data that's actually part of the object.

You need the caller magic so you're localizing $a and $b in the caller's package, which is where Perl is going to look for them. It's creating global variables that only exist while that sub is being called.

Note that you will get a 'name used only once' with warnings; I'm sure there's some hoops you can jump through to avoid this, somehow.

like image 91
Eevee Avatar answered Sep 20 '22 14:09

Eevee