Reputation: 1701
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?
Upvotes: 10
Views: 2466
Reputation: 5318
Just in case anyone is interested, a copy-and-paste from List::MoreUtils::PP v.0.428 (as of December 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
It only differs from the sample above in the area affected by no strict 'refs';
. Probably can't be done without no strict at all.
Upvotes: 0
Reputation: 67028
$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";
}
}
Upvotes: 14