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   15053 use 5.006;
  7         19  
  7         226  
4              
5 7     7   26 use strict;
  7         9  
  7         177  
6 7     7   31 use warnings;
  7         13  
  7         297  
7              
8             =head1 NAME
9              
10             Variable::Temp - Temporarily change the value of a variable.
11              
12             =head1 VERSION
13              
14             Version 0.02
15              
16             =cut
17              
18             our $VERSION;
19             BEGIN {
20 7     7   148 $VERSION = '0.02';
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   3110 use Variable::Magic 0.51;
  7         5951  
  7         254  
43              
44 7     7   2874 use Scope::Upper;
  7         4539  
  7         2853  
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 15692 my $var = $_[0];
98 44         105 my $target = Scope::Upper::UP;
99 44         40 my $ret;
100 44         53 my $type = ref $var;
101 44 100       95 if ($type eq 'ARRAY') {
    100          
102 14         29 my @save = @$var;
103 14     14   60 &Scope::Upper::reap(sub { @$var = @save } => $target);
  14         7708  
104 14         17 my $token;
105 14         54 Variable::Magic::cast($token, $wiz, $var);
106 14         22 $ret = \$token;
107             } elsif ($type eq 'HASH') {
108 14         34 my %save = %$var;
109 14     14   53 &Scope::Upper::reap(sub { %$var = %save } => $target);
  14         7052  
110 14         12 my $token;
111 14         40 Variable::Magic::cast($token, $wiz, $var);
112 14         22 $ret = \$token;
113             } else { # $type eq 'SCALAR' || $type eq 'REF'
114 16         15 my $save = $$var;
115 16     16   75 &Scope::Upper::reap(sub { $$var = $save } => $target);
  16         4031  
116 16         20 $$var = undef;
117 16         16 $ret = $var;
118             }
119 44         131 $$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 14147 my $var = $_[0];
139 40         117 my $target = Scope::Upper::UP;
140 40         55 my $type = ref $var;
141 40 100       84 if ($type eq 'ARRAY') {
    100          
142 14         25 my @save = @$var;
143 14     14   51 &Scope::Upper::reap(sub { @$var = @save } => $target);
  14         6387  
144 14 100       24 @$var = @_ >= 2 ? @{$_[1]} : ();
  12         27  
145             } elsif ($type eq 'HASH') {
146 14         35 my %save = %$var;
147 14     14   57 &Scope::Upper::reap(sub { %$var = %save } => $target);
  14         6782  
148 14 100       30 %$var = @_ >= 2 ? %{$_[1]} : ();
  12         43  
149             } else { # $type eq 'SCALAR' || $type eq 'REF'
150 12         11 my $save = $$var;
151 12     12   56 &Scope::Upper::reap(sub { $$var = $save } => $target);
  12         3992  
152 12         17 $$var = $_[1];
153             }
154 40         61 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   34 use base 'Exporter';
  7         11  
  7         668  
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