=head1 SYNOPSIS
- use Variable::Magic qw/wizard cast dispell/;
-
- my $wiz = wizard set => sub { print STDERR "now set to ${$_[0]}!\n" };
- my $a = 1;
- cast $a, $wiz;
- $a = 2; # "now set to 2!"
- dispell $a, $wiz;
- $a = 3 # (nothing)
+ use Variable::Magic qw/wizard cast VMG_OP_INFO_NAME/;
+
+ { # A variable tracer
+ my $wiz = wizard set => sub { print "now set to ${$_[0]}!\n" },
+ free => sub { print "destroyed!\n" };
+
+ my $a = 1;
+ cast $a, $wiz;
+ $a = 2; # "now set to 2!"
+ } # "destroyed!"
+
+ { # A hash with a default value
+ my $wiz = wizard data => sub { $_[1] },
+ fetch => sub { $_[2] = $_[1] unless exists $_[0]->{$_[2]}; () },
+ store => sub { print "key $_[2] stored in $_[-1]\n" },
+ copy_key => 1,
+ op_info => VMG_OP_INFO_NAME;
+
+ my %h = (_default => 0, apple => 2);
+ cast %h, $wiz, '_default';
+ print $h{banana}, "\n"; # "0", because the 'banana' key doesn't exist in %h
+ $h{pear} = 1; # "key pear stored in helem"
+ }
=head1 DESCRIPTION
set => sub { print STDERR "set to ${$_[0]}\n" },
free => sub { print STDERR "${$_[0]} was deleted\n" }
+Note that C<free> callbacks are I<never> called during global destruction, as there's no way to ensure that the wizard and the C<free> coderef weren't destroyed before the scalar.
+
=cut
sub wizard {
If you want to overcome the possible deletion of the C<'TZ'> entry, you have no choice but to rely on C<store> uvar magic.
+C<cast> can be called from any magical callback, and in particular from C<data>.
+This allows you to recursively cast magic on datastructures :
+
+ my $wiz;
+ $wiz = wizard
+ data => sub {
+ my ($var, $depth) = @_;
+ $depth ||= 0;
+ my $r = ref $var;
+ if ($r eq 'ARRAY') {
+ &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for @$var;
+ } elsif ($r eq 'HASH') {
+ &cast((ref() ? $_ : \$_), $wiz, $depth + 1) for values %$var;
+ }
+ return $depth;
+ },
+ free => sub {
+ my ($var, $depth) = @_;
+ my $r = ref $var;
+ print "free $r at depth $depth\n";
+ ();
+ };
+
+ {
+ my %h = (
+ a => [ 1, 2 ],
+ b => { c => 3 }
+ );
+ cast %h, $wiz;
+ }
+
+When C<%h> goes out of scope, this will print something among the lines of :
+
+ free HASH at depth 0
+ free HASH at depth 1
+ free SCALAR at depth 2
+ free ARRAY at depth 1
+ free SCALAR at depth 3
+ free SCALAR at depth 3
+
+Of course, this example does nothing with the values that are added after the C<cast>.
+
=head2 C<getdata>
getdata [$@%&*]var, [$wiz|$sig]