I was specifically interested in why the particular corner I've backed myself into doesn't work.
{
my $foo = 1;
sub level : lvalue {$foo}
}
print level();
{
local level() = 2;
print level();
}
print level();
__END__
Because of my - it's a closure - and, as stated in perlsub
A "local" is simply a modifier on an lvalue expression.
No matter whether you localize the lvalue expression successfully or not, it is not the variable the lvalue sub operates on which is localized. An lvalue sub results in an lvalue upon which the operation in question is performed at subroutine return, and on the left-hand-side of the lvalue sub call you find the result of that operation. So, I guess you are effectively localizing the subroutine's return value, which isn't what you expected.
In your code above, $foo is a lexically scoped scalar, and your subroutine is a "closure" - it closes over the scalar, which furthermore it isn't visible anywhere but in that scope, and as such can't be localized.
Were you successfully operating with local upon that lexical variable, perl would have died with
Can't localize lexical variable $foo at __FILE__ line __LINE__.
Remember that my is a compile time directive, while local is runtime (see my/local, space/time (was: Re: The difference between my and local)).
To localize a subroutine proper, you have to assign a coderef to its typeglob (*foo)
{
local *foo = sub : lvalue { print "wuff: $foo\n"; $foo };
}
to make the localization effective (I guess it is optimized away otherwise, but I haven't checked that).
Try to work out what is happening here:
$\ = "\n";
$foo = 3;
sub foo :lvalue { $foo }
{
local *foo = sub :lvalue {
$foo *= 1.25;
$foo;
};
{
local $foo;
print '1: ',(foo() = 4);
print '2: ',(foo() *= 4);
foo() = 2;
local *foo = sub :lvalue {
local $foo = $foo * 1.25;
$foo;
};
print '3: ',(foo() *= 4);
}
local $foo = 4;
print '4: ',(foo() /= 2);
print '5: ',foo();
}
print '6: ',foo();
__END__
1: 4
2: 20
3: 10
4: 2.5
5: 3.125
6: 3
All that said, an attempt to localize an lvalue sub with
local foo() = 2;
should result at least in a warning as
Useless localizing of a subroutine return value
or the like.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
|