Package::Stash - Routines for manipulating stashes
version 0.40
my $stash = Package::Stash->new('Foo');
$stash->add_symbol('%foo', {bar => 1});
# $Foo::foo{bar} == 1
$stash->has_symbol('$foo') # false
my $namespace = $stash->namespace;
*{ $namespace->{foo} }{HASH} # {bar => 1}
Manipulating stashes (Perl's symbol tables) is occasionally necessary, but
incredibly messy, and easy to get wrong. This module hides all of that behind a
simple API.
NOTE: Most methods in this class require a variable specification that includes
a sigil. If this sigil is absent, it is assumed to represent the IO slot.
Due to limitations in the typeglob API available to perl code, and to typeglob
manipulation in perl being quite slow, this module provides two
implementations - one in pure perl, and one using XS. The XS implementation is
to be preferred for most usages; the pure perl one is provided for cases where
XS modules are not a possibility. The current implementation in use can be set
by setting $ENV{PACKAGE_STASH_IMPLEMENTATION} or
$Package::Stash::IMPLEMENTATION before loading Package::Stash (with the
environment variable taking precedence), otherwise, it will use the XS
implementation if possible, falling back to the pure perl one.
Creates a new Package::Stash object, for the package given as the only
argument.
Returns the name of the package that this object represents.
Returns the raw stash itself.
Adds a new package symbol, for the symbol given as $variable , and optionally
gives it an initial value of $value . $variable should be the name of
variable including the sigil, so
Package::Stash->new('Foo')->add_symbol('%foo')
will create %Foo::foo .
Valid options (all optional) are filename , first_line_num , and
last_line_num .
$opts{filename} , $opts{first_line_num} , and $opts{last_line_num} can
be used to indicate where the symbol should be regarded as having been defined.
Currently these values are only used if the symbol is a subroutine ('& '
sigil) and only if $^P & 0x10 is true, in which case the special %DB::sub
hash is updated to record the values of filename , first_line_num , and
last_line_num for the subroutine. If these are not passed, their values are
inferred (as much as possible) from caller information.
Removes all package variables with the given name, regardless of sigil.
Returns whether or not the given package variable (including sigil) exists.
Returns the value of the given package variable (including sigil).
Like get_symbol , except that it will return an empty hashref or
arrayref if the variable doesn't exist.
Removes the package variable described by $variable (which includes the
sigil); other variables with the same name but different sigils will be
untouched.
Returns a list of package variable names in the package, without sigils. If a
type_filter is passed, it is used to select package variables of a given
type, where valid types are the slots of a typeglob ('SCALAR', 'CODE', 'HASH',
etc). Note that if the package contained any BEGIN blocks, perl will leave
an empty typeglob in the BEGIN slot, so this will show up if no filter is
used (and similarly for INIT , END , etc).
Returns a hashref, keyed by the variable names in the package. If
$type_filter is passed, the hash will contain every variable of that type in
the package as values, otherwise, it will contain the typeglobs corresponding
to the variable names (basically, a clone of the stash).
This is especially useful for debuggers and profilers, which use %DB::sub to
determine where the source code for a subroutine can be found. See
http://perldoc.perl.org/perldebguts.html#Debugger-Internals for more
information about %DB::sub .
It is important to note, that when working with scalar variables, the default
behavior is to copy values.
my $stash = Package::Stash->new('Some::Namespace');
my $variable = 1;
# $Some::Namespace::name is a copy of $variable
$stash->add_symbol('$name', $variable);
$variable++
# $Some::Namespace::name == 1 , $variable == 2
This will likely confuse people who expect it to work the same as typeglob
assignment, which simply creates new references to existing variables.
my $variable = 1;
{
no strict 'refs';
# assign $Package::Stash::name = $variable
*{'Package::Stash::name'} = \$variable;
}
$variable++ # affects both names
If this behaviour is desired when working with Package::Stash, simply pass
Package::Stash a scalar ref:
my $stash = Package::Stash->new('Some::Namespace');
my $variable = 1;
# $Some::Namespace::name is now $variable
$stash->add_symbol('$name', \$variable);
$variable++
# $Some::Namespace::name == 2 , $variable == 2
This will be what you want as well if you're ever working with Readonly
variables:
use Readonly;
Readonly my $value, 'hello';
$stash->add_symbol('$name', \$value); # reference
print $Some::Namespace::name; # hello
# Tries to modify the read-only 'hello' and dies.
$Some::Namespace::name .= " world";
$stash->add_symbol('$name', $value); # copy
print $Some::Namespace::name; # hello
# No problem, modifying a copy, not the original
$Some::Namespace::name .= " world";
Based on code from the Class::MOP::Package manpage, by Stevan Little and the Moose
Cabal.
Bugs may be submitted through the RT bug tracker
(or bug-Package-Stash@rt.cpan.org).
This software is copyright (c) 2022 by Jesse Luehrs.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
|