=head1 VERSION
-Version 0.01
+Version 0.02
=cut
our $VERSION;
BEGIN {
- $VERSION = '0.01';
+ $VERSION = '0.02';
}
=head1 SYNOPSIS
package X;
- use Scope::Upper qw/reap localize localize_elem/;
+ use Scope::Upper qw/reap localize localize_elem localize_delete/;
sub desc { shift->{desc} }
my $x = do { no strict 'refs'; ${$pkg.'::x'} }; # Get the $x in the scope
CORE::warn($x->desc . ': ' . join('', @_));
} => 1;
+
+ localize_delete '@ARGV', $#ARGV => 1; # delete last @ARGV element
}
package Y;
{
X::set_tag('pie');
- # $x is now a X object
+ # $x is now a X object, and @ARGV has one element less
warn 'what'; # warns "pie: what at ..."
...
} # "pie: done" is printed
=head1 DESCRIPTION
This module lets you defer actions that will take place when the control flow returns into an upper scope.
-Currently, you can hook an upper scope end, or localize variables and array/hash values in higher contexts.
+Currently, you can hook an upper scope end, or localize variables, array/hash values or deletions of elements in higher contexts.
=head1 FUNCTIONS
=item *
-A string beginning with a sigil, representing the symbol to localize and assign to.
-If the sigil is C<'$'>, then C<$value> isn't dereferenced, that is
+A string beginning with a sigil, representing the symbol to localize and to assign to.
+If the sigil is C<'$'>, L</localize> follows the same syntax as C<local $x = $value>, i.e. C<$value> isn't dereferenced.
+For example,
localize '$x', \'foo' => 0;
will set C<$x> to a reference to the string C<'foo'>.
-Other sigils behave as if a glob was passed.
+Other sigils (C<'@'>, C<'%'>, C<'&'> and C<'*'>) require C<$value> to be a reference of the corresponding type.
-The symbol is resolved when the actual localization takes place and not when C<localize> is called.
+When the symbol is given by a string, it is resolved when the actual localization takes place and not when C<localize> is called.
This means that
sub tag { localize '$x', $_[0] => 1; }
If C<$what> is a glob, the slot to fill is determined from which type of reference C<$value> is ; otherwise it's inferred from the sigil.
C<$key> is either an array index or a hash key, depending of which kind of variable you localize.
+=head2 C<localize_delete $what, $key, $level>
+
+Similiar to L</localize>, but for deleting variables or array/hash elements.
+C<$what> can be:
+
+=over 4
+
+=item *
+
+A glob, in which case C<$key> is ignored and the call is equivalent to C<local *x>.
+
+=item *
+
+A string beginning with C<'@'> or C<'%'>, for which the call is equivalent to respectiveley C<local $a[$key]; delete $a[$key]> and C<local $h{$key}; delete $h{$key}>.
+
+=item *
+
+A string beginning with C<'&'>, which more or less does C<undef &func> in the upper scope.
+It's actually more powerful, as C<&func> won't even C<exists> anymore.
+C<$key> is ignored.
+
+=back
+
=head2 C<TOPLEVEL>
Returns the level that currently represents the highest scope.
=head1 EXPORT
-The functions L</reap>, L</localize>, L</localize_elem> and L</TOPLEVEL> are only exported on request, either individually or by the tags C<':funcs'> and C<':all'>.
+The functions L</reap>, L</localize>, L</localize_elem>, L</localize_delete> and L</TOPLEVEL> are only exported on request, either individually or by the tags C<':funcs'> and C<':all'>.
=cut
our @EXPORT = ();
our %EXPORT_TAGS = (
- funcs => [ qw/reap localize localize_elem TOPLEVEL/ ],
+ funcs => [ qw/reap localize localize_elem localize_delete TOPLEVEL/ ],
);
our @EXPORT_OK = map { @$_ } values %EXPORT_TAGS;
$EXPORT_TAGS{'all'} = [ @EXPORT_OK ];
+=head1 CAVEATS
+
+Be careful that local variables are restored in the reverse order in which they were localized.
+Consider those examples:
+
+ local $x = 0;
+ {
+ reap sub { print $x } => 0;
+ local $x = 1;
+ ...
+ }
+ # prints '0'
+ ...
+ {
+ local $x = 1;
+ reap sub { $x = 2 } => 0;
+ ...
+ }
+ # $x is 0
+
+The first case is "solved" by moving the C<local> before the C<reap>, and the second by using L</localize> instead of L</reap>.
+
+L</reap>, L</localize> and L</localize_elem> effects can't cross C<BEGIN> blocks, hence calling those functions in C<import> is deemed to be useless.
+This is an hopeless case because C<BEGIN> blocks are executed once while localizing constructs should do their job at each run.
+
=head1 DEPENDENCIES
L<XSLoader> (standard since perl 5.006).
perldoc Scope::Upper
+Tests code coverage report is available at L<http://www.profvince.com/perl/cover/Scope-Upper>.
+
=head1 ACKNOWLEDGEMENTS
Inspired by Ricardo Signes.