Как использовать $ a и $ b в подпрограмме Perl - PullRequest
10 голосов
/ 02 января 2012

Я хотел бы использовать переменные $a и $b в моих анонимных двоичных функциях, как это сделано в sort {$a <=> $b} (1, 2, 3), но я не могу понять, почему код, такой как

#!/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";
    }
}    

не работает. Пока

#!/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";
    }
}

отлично работает.

Что я делаю не так?

Ответы [ 2 ]

14 голосов
/ 02 января 2012

$a и $b - специальные переменные пакета.Вы звоните Foo::Bar из своего пакета main, поэтому вам нужно установить $main::a и $main::b, чтобы он работалВы можете использовать caller, чтобы получить имя вызывающего пакета.Это должно работать:

#!/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";
    }
}    
0 голосов
/ 25 декабря 2017

На всякий случай, если кому-то интересно, скопируйте и вставьте из Список :: MoreUtils :: PP v.0.428 (по состоянию на декабрь 2017 года):

# begin copyrighted content
sub reduce_u(&@)
{
    my $code = shift;

    # Localise $a, $b
    my ($caller_a, $caller_b) = do
    {
        my $pkg = caller();
        no strict 'refs';
        \*{$pkg . '::a'}, \*{$pkg . '::b'};
    };

    local (*$caller_a, *$caller_b);
    *$caller_a = \();
    for (0 .. $#_)
    {
        *$caller_b = \$_[$_];
        *$caller_a = \($code->());
    }

    ${*$caller_a};
}
# end copyrighted content

Этоотличается от приведенного выше образца только областью, на которую влияет no strict 'refs';.Вероятно, не может быть сделано без каких-либо строгих.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...