perlscopeglobal-variablesspecial-variables

How to use $a and $b in Perl subroutine


I would like to use $a and $b variables in my anonimous binary functions like it is done in sort {$a <=> $b} (1, 2, 3) but I can not figure out why code like

#!/usr/bin/env perl
use strict;
use warnings;

Foo::Bar(sub { $a + $b });

package Foo;
sub Bar {
    my ($function) = @_; 

    for my $i (1, 2, 3) {
        local ($a, $b) = ($i, $i);
        print $function->() . "\n";
    }
}    

does not work. While

#!/usr/bin/env perl
use strict;
use warnings;

Foo::Bar(sub { $_ });

package Foo;
sub Bar {
    my ($function) = @_; 

    for my $i (1, 2, 3) {
        local $_ = $i;
        print $function->() . "\n";
    }
}

works fine.

What am I doing wrong?


Solution

  • $a and $b are special package variables. You're calling Foo::Bar from within your main package, so you need to set $main::a and $main::b to get it to work. You can use caller to get the name of the calling package. This should work:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    Foo::Bar(sub { $a + $b });
    
    package Foo;
    sub Bar {
        my ($function) = @_; 
        my $pkg = caller;
    
        for my $i (1, 2, 3) {
            no strict 'refs';
            local *{ $pkg . '::a' } = \$i;
            local *{ $pkg . '::b' } = \$i;
            print $function->() . "\n";
        }
    }