Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 333
alexanderkuk Avatar asked Jan 02 '12 18:01

alexanderkuk


People also ask

How do you pass arguments in Perl subroutine?

Passing Arguments to a Subroutine You can pass various arguments to a subroutine like you do in any other programming language and they can be acessed inside the function using the special array @_. Thus the first argument to the function is in $_[0], the second is in $_[1], and so on.

How do you call a subroutine from another file in Perl?

If you have subroutines defined in another file, you can load them in your program by using the use , do or require statement. A Perl subroutine can be generated at run-time by using the eval() function. You can call a subroutine directly or indirectly via a reference, a variable or an object.


1 Answers

$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";
    }
}    
like image 154
friedo Avatar answered Sep 27 '22 22:09

friedo