How to localize a variable in the upper region in Perl?

Several times I came across the following pattern when developing Perl modules that use AUTOLOAD methods or other routine methods:

 sub AUTOLOAD { my $self = $_[0]; my $code = $self->figure_out_code_ref( $AUTOLOAD ); goto &$code; } 

This works fine, and caller sees the correct scope.

Now what I would like to do is locally set $_ to $self at runtime &$code . Which would be something like this:

 sub AUTOLOAD { my $self = $_[0]; my $code = $self->figure_out_code_ref( $AUTOLOAD ); local *_ = \$self; # and now the question is how to call &$code # goto &$code; # wont work since local scope changes will # be unrolled before the goto # &$code; # will preserve the local, but caller will report an # additional stack frame } 

caller packaging solutions are unacceptable due to performance and dependency issues. So this excludes the second option.

Returning to the first, the only way to prevent a new $_ value from going out of scope during goto is either to not localize the change (not a viable option), or to implement some kind of uplevel_local or goto_with_local .

I played with all kinds of permutations involving PadWalker , Sub::Uplevel , Scope::Upper , B::Hooks::EndOfScope and others, but could not find a reliable solution that clears $_ at the right time and does not complete the caller .

Has anyone found a template that works in this case?

(SO question: How can I localize Perl variables in another stack frame? is connected, but saving caller not a requirement, and ultimately the answer should have used a different approach, so the solution does not help in this case)

+6
perl goto local
source share
2 answers

Sub :: Uplevel seems to work - at least for a simple case not related to AUTOLOAD:

 use strict; use warnings; use Sub::Uplevel; $_ = 1; bar(); sub foo { printf "%s %s %d - %s\n", caller, $_ } sub bar { my $code = \&foo; my $x = 2; local *_ = \$x; uplevel 1, $code; } 

Output:

 main c:\temp\foo.pl 6 - 2 

Of course, this does not actually localize the variable in the parent scope, but I do not think that you really want to do this, even if you could. You want to localize $_ for the duration of the call.

+1
source share

Perlfunc documentation for goto indicated (in italics)

The goto-&NAME form is very different from other "goto" forms. In fact, this is not what it is in the normal sense, and does not have the stigma associated with other gotos. Instead, it exits the current routine (losing any changes set by local ) ...

What performance problems allow indirectness at startup, but not through the shell?

+1
source share

All Articles