use warnings;
use strict;
sub a { "unchanged" };
sub print_a { print a(), "\n" };
####
no strict 'refs';
no warnings 'redefine';
{
local *a = sub { "changed" };
print_a(); # prints "changed"
}
##
##
print_a(); # prints "unchanged"
##
##
sub localize_a_and_call_fn(&@) {
my ($fn, @args) = @_;
local *a = sub { "changed" };
$fn->(@args);
}
##
##
localize_a_and_call_fn( \&print_a );
# prints "changed"
localize_a_and_call_fn {
print "a() => ", a(), "\n";
};
# prints "a() => changed"
##
##
sub localize_and_call_fn
{
my ($locals, $fn, @args) = @_;
local *$_ = sub { "changed" } for @$locals;
$fn->(@args);
}
##
##
localize_and_call_fn( [qw(a b c)], \&print_a );
# prints "unchanged"
##
##
# for (@$locals) {
# local *$_ = sub { "changed" };
# }
##
##
sub localize_and_call_fn_2
{
my ($locals, $fn, @args) = @_;
for my $sym (@$locals) {
my $f = $fn;
$fn = sub {
local *$sym = sub { "changed" };
$f->(@_);
}
}
$fn->(@args);
}
localize_and_call_fn_2( [qw(a b c)], \&print_a );
# prints "changed"
##
##
# (sub {
# local *c = sub { "changed" };
# (sub {
# local *b = sub { "changed" };
# (sub {
# local *a = sub { "changed" };
# (\&print_a)->(@_);
# })->(@_)
# })->(@_)
# })->();