The following code prints <oof foo zab><foo foo baz>:
use v5.36;
use warnings;
our $foo = 'foo';
our %bar = (
foo => \$foo,
baz => 'baz',
);
{
local ($foo, %bar) = ($foo, %bar);
($foo, $bar{baz}) = qw(oof zab);
print "<$foo ${$bar{foo}} $bar{baz}>";
}
print "<$foo ${$bar{foo}} $bar{baz}>";
Is there a way to make it print <oof oof zab><foo foo baz> without copy/pasting %bars definition into the inner scope?
EDIT:
I realize that I have phrased my question poorly.
The outer scope represents some given code with many such $foos and %bars as well as functions which behave according to those variables.
The inner scope represents tests for the outer scope, where I wanted to localize variables, modify them and test how the functions behave. Each test was supposed to start with the initial conditions, thus the local. It is not feasible to duplicate the many variable assignments into the inner scope, because that might become outdated quickly.
My question might look like an xy-problem, but I had hoped that locals current behaviour is a perl bug.
use Sub::ScopeFinalizer qw( scope_finalizer );
{
my $old_foo = $foo;
my $guard = scope_finalizer { $foo = $old_foo };
$foo = "oof";
say $bar{ foo }->$*; # oof
}
say $bar{ foo }->$*; # foo
Since you're using 5.36, you could forgo the module in lieu of an experimental feature added that version.
use experimental qw( defer );
{
my $old_foo = $foo;
defer { $foo = $old_foo };
$foo = "oof";
say $bar{ foo }->$*; # oof
}
say $bar{ foo }->$*; # foo
Without using any extra modules:
use v5.36;
use warnings;
our $foo = 'foo';
our %bar = (
foo => \$foo,
baz => 'baz',
);
{
local $foo = 'oof';
local $bar{foo} = \$foo;
print "<$foo ${$bar{foo}} $bar{baz}>";
}
print "<$foo ${$bar{foo}} $bar{baz}>";
prints <oof oof baz><foo foo baz>.
You can localize a single hash entry even if the hash is lexical (i.e. created as my %bar), but you can not localize a lexical scalar. The local built-in replaces the variable itself, not just its value, so $bar{foo} continues to refer to the original $foo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With