File Coverage

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


line stmt bran cond sub pod time code
1             package Variable::Temp;
2              
3 7     7   56708 use 5.006;
  7         60  
4              
5 7     7   46 use strict;
  7         15  
  7         159  
6 7     7   38 use warnings;
  7         16  
  7         1037  
7              
8             =head1 NAME
9              
10             Variable::Temp - Temporarily change the value of a variable.
11              
12             =head1 VERSION
13              
14             Version 0.04
15              
16             =cut
17              
18             our $VERSION;
19             BEGIN {
20 7     7   224 $VERSION = '0.04';
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   2513 use Variable::Magic 0.51;
  7         8665  
  7         417  
43              
44 7     7   2723 use Scope::Upper;
  7         14441  
  7         4867  
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 38650 my $var = $_[0];
98 44         203 my $target = Scope::Upper::UP;
99 44         109 my $ret;
100 44         143 my $type = ref $var;
101 44 100       201 if ($type eq 'ARRAY') {
    100          
102 14         76 my @save = @$var;
103 14     14   134 &Scope::Upper::reap(sub { @$var = @save } => $target);
  14         16683  
104 14         35 my $token;
105 14         109 Variable::Magic::cast($token, $wiz, $var);
106 14         52 $ret = \$token;
107             } elsif ($type eq 'HASH') {
108 14         84 my %save = %$var;
109 14     14   137 &Scope::Upper::reap(sub { %$var = %save } => $target);
  14         18865  
110 14         33 my $token;
111 14         117 Variable::Magic::cast($token, $wiz, $var);
112 14         52 $ret = \$token;
113             } else { # $type eq 'SCALAR' || $type eq 'REF'
114 16         39 my $save = $$var;
115 16     16   130 &Scope::Upper::reap(sub { $$var = $save } => $target);
  16         9201  
116 16         37 $$var = undef;
117 16         40 $ret = $var;
118             }
119 44         243 $$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 41     41 1 31955 my $var = $_[0];
139 41         130 my $target = Scope::Upper::UP;
140 41         94 my $type = ref $var;
141 41 100       122 if ($type eq 'ARRAY') {
    100          
142 14         38 my @save = @$var;
143 14     14   92 &Scope::Upper::reap(sub { @$var = @save } => $target);
  14         13510  
144 14 100       49 @$var = @_ >= 2 ? @{$_[1]} : ();
  12         31  
145             } elsif ($type eq 'HASH') {
146 14         52 my %save = %$var;
147 14     14   91 &Scope::Upper::reap(sub { %$var = %save } => $target);
  14         13970  
148 14 100       37 %$var = @_ >= 2 ? %{$_[1]} : ();
  12         47  
149             } else { # $type eq 'SCALAR' || $type eq 'REF'
150 13         24 my $save = $$var;
151 13     13   86 &Scope::Upper::reap(sub { $$var = $save } => $target);
  13         11271  
152 13         33 $$var = $_[1];
153             }
154 41         108 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   66 use base 'Exporter';
  7         19  
  7         1059  
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,2017 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