|
Packit |
074f87 |
package PadWalker;
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
use strict;
|
|
Packit |
074f87 |
use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
require Exporter;
|
|
Packit |
074f87 |
require DynaLoader;
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
require 5.008;
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
@ISA = qw(Exporter DynaLoader);
|
|
Packit |
074f87 |
@EXPORT_OK = qw(peek_my peek_our closed_over peek_sub var_name set_closed_over);
|
|
Packit |
074f87 |
%EXPORT_TAGS = (all => \@EXPORT_OK);
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
$VERSION = '2.3';
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
bootstrap PadWalker $VERSION;
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
sub peek_my;
|
|
Packit |
074f87 |
sub peek_our;
|
|
Packit |
074f87 |
sub closed_over;
|
|
Packit |
074f87 |
sub peek_sub;
|
|
Packit |
074f87 |
sub var_name;
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
1;
|
|
Packit |
074f87 |
__END__
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=head1 NAME
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
PadWalker - play with other peoples' lexical variables
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=head1 SYNOPSIS
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
use PadWalker qw(peek_my peek_our peek_sub closed_over);
|
|
Packit |
074f87 |
...
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=head1 DESCRIPTION
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
PadWalker is a module which allows you to inspect (and even change!)
|
|
Packit |
074f87 |
lexical variables in any subroutine which called you. It will only
|
|
Packit |
074f87 |
show those variables which are in scope at the point of the call.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
PadWalker is particularly useful for debugging. It's even
|
|
Packit |
074f87 |
used by Perl's built-in debugger. (It can also be used
|
|
Packit |
074f87 |
for evil, of course.)
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
I wouldn't recommend using PadWalker directly in production
|
|
Packit |
074f87 |
code, but it's your call. Some of the modules that use
|
|
Packit |
074f87 |
PadWalker internally are certainly safe for and useful
|
|
Packit |
074f87 |
in production.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=over 4
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=item peek_my LEVEL
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=item peek_our LEVEL
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
The LEVEL argument is interpreted just like the argument to C<caller>.
|
|
Packit |
074f87 |
So C<peek_my(0)> returns a reference to a hash of all the C<my>
|
|
Packit |
074f87 |
variables that are currently in scope;
|
|
Packit |
074f87 |
C<peek_my(1)> returns a reference to a hash of all the C<my>
|
|
Packit |
074f87 |
variables that are in scope at the point where the current
|
|
Packit |
074f87 |
sub was called, and so on.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
C<peek_our> works in the same way, except that it lists
|
|
Packit |
074f87 |
the C<our> variables rather than the C<my> variables.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
The hash associates each variable name with a reference
|
|
Packit |
074f87 |
to its value. The variable names include the sigil, so
|
|
Packit |
074f87 |
the variable $x is represented by the string '$x'.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
For example:
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
my $x = 12;
|
|
Packit |
074f87 |
my $h = peek_my (0);
|
|
Packit |
074f87 |
${$h->{'$x'}}++;
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
print $x; # prints 13
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
Or a more complex example:
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
sub increment_my_x {
|
|
Packit |
074f87 |
my $h = peek_my (1);
|
|
Packit |
074f87 |
${$h->{'$x'}}++;
|
|
Packit |
074f87 |
}
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
my $x=5;
|
|
Packit |
074f87 |
increment_my_x;
|
|
Packit |
074f87 |
print $x; # prints 6
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=item peek_sub SUB
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
The C<peek_sub> routine takes a coderef as its argument, and returns a hash
|
|
Packit |
074f87 |
of the C<my> variables used in that sub. The values will usually be undefined
|
|
Packit |
074f87 |
unless the sub is in use (i.e. in the call-chain) at the time. On the other
|
|
Packit |
074f87 |
hand:
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
my $x = "Hello!";
|
|
Packit |
074f87 |
my $r = peek_sub(sub {$x})->{'$x'};
|
|
Packit |
074f87 |
print "$$r\n"; # prints 'Hello!'
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
If the sub defines several C<my> variables with the same name, you'll get the
|
|
Packit |
074f87 |
last one. I don't know of any use for C<peek_sub> that isn't broken as a result
|
|
Packit |
074f87 |
of this, and it will probably be deprecated in a future version in favour of
|
|
Packit |
074f87 |
some alternative interface.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=item closed_over SUB
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
C<closed_over> is similar to C<peek_sub>, except that it only lists
|
|
Packit |
074f87 |
the C<my> variables which are used in the subroutine but defined outside:
|
|
Packit |
074f87 |
in other words, the variables which it closes over. This I<does> have
|
|
Packit |
074f87 |
reasonable uses: see L<Data::Dump::Streamer>, for example (a future version
|
|
Packit |
074f87 |
of which may in fact use C<closed_over>).
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=item set_closed_over SUB, HASH_REF
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
C<set_closed_over> reassigns the pad variables that are closed over by the subroutine.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
The second argument is a hash of references, much like the one returned from C<closed_over>.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=item var_name LEVEL, VAR_REF
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=item var_name SUB, VAR_REF
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
C<var_name(sub, var_ref)> returns the name of the variable referred to
|
|
Packit |
074f87 |
by C<var_ref>, provided it is a C<my> variable used in the sub. The C<sub>
|
|
Packit |
074f87 |
parameter can be either a CODE reference or a number. If it's a number,
|
|
Packit |
074f87 |
it's treated the same way as the argument to C<peek_my>.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
For example,
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
my $foo;
|
|
Packit |
074f87 |
print var_name(0, \$foo); # prints '$foo'
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
sub my_name {
|
|
Packit |
074f87 |
return var_name(1, shift);
|
|
Packit |
074f87 |
}
|
|
Packit |
074f87 |
print my_name(\$foo); # ditto
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=back
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=head1 AUTHOR
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
Robin Houston <robin@cpan.org>
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
With contributions from Richard Soberberg, Jesse Luehrs and
|
|
Packit |
074f87 |
Yuval Kogman, bug-spotting from Peter Scott, Dave Mitchell and
|
|
Packit |
074f87 |
Goro Fuji, and suggestions from demerphq.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=head1 SEE ALSO
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
Devel::LexAlias, Devel::Caller, Sub::Parameters
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=head1 COPYRIGHT
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
Copyright (c) 2000-2009, Robin Houston. All Rights Reserved.
|
|
Packit |
074f87 |
This module is free software. It may be used, redistributed
|
|
Packit |
074f87 |
and/or modified under the same terms as Perl itself.
|
|
Packit |
074f87 |
|
|
Packit |
074f87 |
=cut
|