+my $wiz;
+$wiz = Variable::Magic::wizard(
+ data => sub { $_[1] },
+ set => sub {
+ my ($token, $var) = @_;
+ &Variable::Magic::dispell($token, $wiz);
+ if (ref $var eq 'ARRAY') {
+ @$var = @$$token;
+ } else {
+ %$var = %$$token;
+ }
+ return;
+ },
+ free => sub {
+ my ($token, $var) = @_;
+ # We need Variable::Magic 0.51 so that dispell in free does not crash.
+ &Variable::Magic::dispell($token, $wiz);
+ if (ref $var eq 'ARRAY') {
+ @$var = ();
+ } else {
+ %$var = ();
+ }
+ },
+);
+
+sub temp (\[$@%]) :lvalue {
+ my $var = $_[0];
+ my $target = Scope::Upper::UP;
+ my $ret;
+ my $type = ref $var;
+ if ($type eq 'ARRAY') {
+ my @save = @$var;
+ &Scope::Upper::reap(sub { @$var = @save } => $target);
+ my $token;
+ Variable::Magic::cast($token, $wiz, $var);
+ $ret = \$token;
+ } elsif ($type eq 'HASH') {
+ my %save = %$var;
+ &Scope::Upper::reap(sub { %$var = %save } => $target);
+ my $token;
+ Variable::Magic::cast($token, $wiz, $var);
+ $ret = \$token;
+ } else { # $type eq 'SCALAR' || $type eq 'REF'
+ my $save = $$var;
+ &Scope::Upper::reap(sub { $$var = $save } => $target);
+ $$var = undef;
+ $ret = $var;
+ }
+ $$ret;