use strict; my %hash = ( a => 1, b => 2, c => 3 ); sub with(\%&) { my ($href, $cref) = @_; my $cmd = join "\n", map sprintf('local $::%s = \\$href->{%s};', $_, $_), keys %$href; eval $cmd . '$cref->()'; warn "$@: $cmd\n" if $@; } with %hash, sub { $$a = 'changed'; print "B=$$b\n"; } ; use Data::Dumper; print Dumper(\%hash);