Как использовать $a и $b в подпрограмме Perl
Я хотел бы использовать $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 ответа
$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";
}
}
На всякий случай, если кому-то интересно, скопируйте и вставьте из List:: 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';
, Вероятно, не может быть сделано без каких-либо строгих вообще.