File Coverage

blib/lib/Variable/Temp.pm
Criterion Covered Total %
statement 61 61 100.0
branch 12 12 100.0
condition n/a
subroutine 15 15 100.0
pod 2 2 100.0
total 90 90 100.0


line stmt bran cond sub pod time code
1             package Variable::Temp;
2              
3 7     7   21344 use 5.006;
  7         18  
  7         233  
4              
5 7     7   26 use strict;
  7         7  
  7         175  
6 7     7   27 use warnings;
  7         14  
  7         339  
7              
8             =head1 NAME
9              
10             Variable::Temp - Temporarily change the value of a variable.
11              
12             =head1 VERSION
13              
14             Version 0.03
15              
16             =cut
17              
18             our $VERSION;
19             BEGIN {
20 7     7   153 $VERSION = '0.03';
21             }
22              
23             =head1 SYNOPSIS
24              
25             use Variable::Temp 'temp';
26              
27             my $x = 1;
28             say $x; # 1
29             {
30             temp $x = 2;
31             say $x; # 2
32             }
33             say $x; # 1
34              
35             =head1 DESCRIPTION
36              
37             This module provides an utility routine that can be used to temporarily change the value of a scalar, array or hash variable, until the end of the current scope is reached where the original value of the variable is restored.
38             It is similar to C, except that it can be applied onto lexicals as well as globals, and that it replaces values by copying the new value into the container variable instead of by aliasing.
39              
40             =cut
41              
42 7     7   3370 use Variable::Magic 0.51;
  7         6047  
  7         307  
43              
44 7     7   3332 use Scope::Upper;
  7         5083  
  7         3320  
45              
46             =head1 FUNCTIONS
47              
48             =head2 C
49              
50             temp $var;
51             temp $var = $value;
52              
53             temp @var;
54             temp @var = \@value;
55              
56             temp %var;
57             temp %var = \%value;
58              
59             Temporarily replaces the value of the lexical or global variable C<$var> by C<$value> (respectively C<@var> by C<@value>, C<%var> by C<%value>), or by C if C<$value> is omitted (respectively empties C<@var> and C<%var> if the second argument is omitted), until the end of the current scope.
60             Any subsequent assignments to this variable in the current (or any inferior) scope will not affect the original value which will be restored into the variable at scope end.
61             Several C calls can be made onto the same variable, and the restore are processed in reverse order.
62              
63             Note that destructors associated with the variable will B be called when C sets the temporary value, but only at the natural end of life of the variable.
64             They will trigger after any destructor associated with the replacement value.
65              
66             Due to a shortcoming in the handling of the C<\$> prototype, which was addressed in C 5.14, the pseudo-statement C will cause compilation errors on C 5.12.x and below.
67             If you want your code to run on these versions of C, you are encouraged to use L instead.
68              
69             =cut
70              
71             my $wiz;
72             $wiz = Variable::Magic::wizard(
73             data => sub { $_[1] },
74             set => sub {
75             my ($token, $var) = @_;
76             &Variable::Magic::dispell($token, $wiz);
77             if (ref $var eq 'ARRAY') {
78             @$var = @$$token;
79             } else {
80             %$var = %$$token;
81             }
82             return;
83             },
84             free => sub {
85             my ($token, $var) = @_;
86             # We need Variable::Magic 0.51 so that dispell in free does not crash.
87             &Variable::Magic::dispell($token, $wiz);
88             if (ref $var eq 'ARRAY') {
89             @$var = ();
90             } else {
91             %$var = ();
92             }
93             },
94             );
95              
96             sub temp (\[$@%]) :lvalue {
97 44     44 1 16698 my $var = $_[0];
98 44         116 my $target = Scope::Upper::UP;
99 44         42 my $ret;
100 44         98 my $type = ref $var;
101 44 100       110 if ($type eq 'ARRAY') {
    100          
102 14         31 my @save = @$var;
103 14     14   73 &Scope::Upper::reap(sub { @$var = @save } => $target);
  14         7832  
104 14         14 my $token;
105 14         60 Variable::Magic::cast($token, $wiz, $var);
106 14         24 $ret = \$token;
107             } elsif ($type eq 'HASH') {
108 14         45 my %save = %$var;
109 14     14   65 &Scope::Upper::reap(sub { %$var = %save } => $target);
  14         8021  
110 14         16 my $token;
111 14         49 Variable::Magic::cast($token, $wiz, $var);
112 14         27 $ret = \$token;
113             } else { # $type eq 'SCALAR' || $type eq 'REF'
114 16         16 my $save = $$var;
115 16     16   82 &Scope::Upper::reap(sub { $$var = $save } => $target);
  16         4076  
116 16         19 $$var = undef;
117 16         21 $ret = $var;
118             }
119 44         128 $$ret;
120             }
121              
122             =head2 C
123              
124             set_temp $var;
125             set_temp $var => $value;
126              
127             set_temp @var;
128             set_temp @var => \@value;
129              
130             set_temp %var;
131             set_temp %var => \%value;
132              
133             A non-lvalue variant of L that can be used with any version of C.
134              
135             =cut
136              
137             sub set_temp (\[$@%];$) {
138 40     40 1 14598 my $var = $_[0];
139 40         89 my $target = Scope::Upper::UP;
140 40         46 my $type = ref $var;
141 40 100       79 if ($type eq 'ARRAY') {
    100          
142 14         28 my @save = @$var;
143 14     14   49 &Scope::Upper::reap(sub { @$var = @save } => $target);
  14         6788  
144 14 100       26 @$var = @_ >= 2 ? @{$_[1]} : ();
  12         26  
145             } elsif ($type eq 'HASH') {
146 14         34 my %save = %$var;
147 14     14   51 &Scope::Upper::reap(sub { %$var = %save } => $target);
  14         7248  
148 14 100       23 %$var = @_ >= 2 ? %{$_[1]} : ();
  12         38  
149             } else { # $type eq 'SCALAR' || $type eq 'REF'
150 12         12 my $save = $$var;
151 12     12   51 &Scope::Upper::reap(sub { $$var = $save } => $target);
  12         4222  
152 12         20 $$var = $_[1];
153             }
154 40         69 return;
155             }
156              
157             =head1 EXPORT
158              
159             The functions L and L are only exported on request by specifying their names in the module import list.
160              
161             =cut
162              
163 7     7   35 use base 'Exporter';
  7         12  
  7         694  
164              
165             our @EXPORT = ();
166             our %EXPORT_TAGS = ();
167             our @EXPORT_OK = qw;
168              
169             =head1 DEPENDENCIES
170              
171             L 5.6.
172              
173             L (core since perl 5).
174              
175             L.
176              
177             L 0.51.
178              
179             =head1 SEE ALSO
180              
181             L.
182              
183             L.
184              
185             =head1 AUTHOR
186              
187             Vincent Pit, C<< >>, L.
188              
189             You can contact me by mail or on C (vincent).
190              
191             =head1 BUGS
192              
193             Please report any bugs or feature requests to C, or through the web interface at L.
194             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
195              
196             =head1 SUPPORT
197              
198             You can find documentation for this module with the perldoc command.
199              
200             perldoc Variable::Temp
201              
202             =head1 COPYRIGHT & LICENSE
203              
204             Copyright 2015 Vincent Pit, all rights reserved.
205              
206             This program is free software; you can redistribute it and/or modify it
207             under the same terms as Perl itself.
208              
209             =cut
210              
211             1; # End of Variable::Temp