PadWalker#

📦 std

Reach into another subroutine’s my and our variables - read them, change them, find out their names - from anywhere on the call stack.

PadWalker is the tool of choice for debuggers, introspection utilities, and any code that needs to look at variables it did not declare. It is what Perl’s own built-in debugger uses, and it is the modern replacement for Devel::LexAlias when you want to alias or substitute a lexical in a caller’s pad.

Every function that walks the stack takes a $level argument interpreted just like the argument to caller:

  • 0 - the current scope.

  • 1 - the scope of whoever called the current sub.

  • 2 - two frames up, and so on.

File scope is a valid destination: asking for a $level deeper than the call stack supports raises Not nested deeply enough.

Returned hashes key on the variable name including its sigil - so $x appears under the key '$x', @items under '@items'. Values are always references to the live variable, so assigning through the reference updates the original.

use PadWalker qw(peek_my closed_over var_name set_closed_over);

sub inner {
    my $vars = peek_my(1);                      # the caller's lexicals
    ${ $vars->{'$count'} }++;                   # change the caller's $count
    return join ",", sort keys %$vars;
}
sub outer {
    my $count = 41;
    my @items = (1, 2);
    my $names = inner();
    print "$names; count is now $count\n";      # $count,@items; count is now 42
}
outer();

my $x = 10;
my $add = sub { $_[0] + $x };
print join(",", keys %{ closed_over($add) }), " | ", var_name(0, \$x), "\n";   # $x | $x
set_closed_over($add, { '$x' => \100 });
print $add->(1), "\n";                          # 101

The functions are peek_my, peek_our, peek_sub (the lexicals a sub declares), closed_over and set_closed_over (the variables a closure captured), and var_name (the name of a variable, given a reference to it). This is a native implementation of PadWalker 2.5; its PadWalker.pm is used unchanged, and nothing is exported by default.

Differences from upstream#

None.

Functions#

Lexical inspection#

peek_my#

Return every my variable in scope at a given call-stack depth as a hash of name-to-reference pairs.

peek_our#

Return every our variable in scope at a given call-stack depth as a hash of name-to-reference pairs.

peek_sub#

Return the my variables declared inside a given subroutine, whether or not the sub is currently on the call stack.

closed_over#

Return the lexicals that a subroutine closes over - the variables it references but did not itself declare.

var_name#

Given a reference to a variable, return the name that variable has in a specified subroutine’s pad - or undef if it is not there.

Lexical modification#

set_closed_over#

Replace the lexicals that a subroutine closes over with a new set of references.