File Coverage

blib/lib/Syntax/Keyword/Dynamically.pm
Criterion Covered Total %
statement 18 19 94.7
branch 3 4 75.0
condition n/a
subroutine 5 5 100.0
pod 0 1 0.0
total 26 29 89.6


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2018-2020 -- leonerd@leonerd.org.uk
5              
6             package Syntax::Keyword::Dynamically 0.12;
7              
8 9     9   1874444 use v5.14;
  9         77  
9 9     9   57 use warnings;
  9         21  
  9         260  
10              
11 9     9   63 use Carp;
  9         24  
  9         2482  
12              
13             require XSLoader;
14             XSLoader::load( __PACKAGE__, our $VERSION );
15              
16             =head1 NAME
17              
18             C - dynamically change the value of a variable
19              
20             =head1 SYNOPSIS
21              
22             use Syntax::Keyword::Dynamically;
23              
24             my $logger = ...;
25              
26             sub operate
27             {
28             dynamically $logger->level = LOG_DEBUG;
29              
30             do_things();
31             }
32              
33             =head1 DESCRIPTION
34              
35             This module provides a syntax plugin that implements a single keyword,
36             C, which alters the behaviour of a scalar assignment operation.
37             Syntactically and semantically it is similar to the built-in perl keyword
38             C, but is implemented somewhat differently to give two key advantages
39             over regular C:
40              
41             =over 2
42              
43             =item *
44              
45             You can C assign to lvalue functions and accessors.
46              
47             =item *
48              
49             You can C assign to regular lexical variables.
50              
51             =back
52              
53             Semantically, the behaviour can be considered equivalent to
54              
55             {
56             my $old = $VAR;
57             $VAR = "new value";
58              
59             ...
60              
61             $VAR = $old;
62             }
63              
64             Except that the old value will also be restored in the case of exceptions,
65             C, C or similar ways to leave the controlling block
66             scope.
67              
68             =cut
69              
70             =head1 KEYWORDS
71              
72             =head2 dynamically
73              
74             {
75             dynamically LVALUE = EXPR;
76             ...
77             }
78              
79             The C keyword modifies the behaviour of the following expression.
80             which must be a scalar assignment. Before the new value is assigned to the
81             lvalue, its current value is captured and stored internally within the Perl
82             interpreter. When execution leaves the controlling block for whatever reason,
83             as part of block scope cleanup the saved value is restored.
84              
85             The LVALUE may be any kind of expression that allows normal scalar assignment;
86             lexical or package scalar variables, elements of arrays or hashes, or the
87             result of calling an C<:lvalue> function or method.
88              
89             If the LVALUE has any GET magic associated with it (including a C
90             method of a tied scalar) then this will be executed exactly once when the
91             C expression is evaluated.
92              
93             If the LVALUE has any SET magic associated with it (including a C
94             method of a tied scalar) then this will be executed exactly once when the
95             C expression is evaluated, and again a second time when the
96             controlling scope is unwound.
97              
98             When the LVALUE being assigned to is a hash element, e.g. one of the following
99             forms
100              
101             dynamically $hash{key} = EXPR;
102             dynamically $href->{key} = EXPR;
103              
104             the assignment additionally ensures to remove the key if it is newly-added,
105             and restores by adding the key back again if it had been deleted in the
106             meantime.
107              
108             =cut
109              
110             sub import
111             {
112 7     7   11052 my $class = shift;
113 7         21 my $caller = caller;
114              
115 7         34 $class->import_into( $caller, @_ );
116             }
117              
118             sub import_into
119             {
120 7     7 0 16 my $class = shift;
121 7         27 my ( $caller, @syms ) = @_;
122              
123 7         21 my %syms = map { $_ => 1 } @syms;
  1         10  
124 7         54 $^H{"Syntax::Keyword::Dynamically/dynamically"}++;
125              
126 7 100       41 _enable_async_mode() if delete $syms{'-async'};
127              
128 7 50       8406 croak "Unrecognised import symbols @{[ keys %syms ]}" if keys %syms;
  0            
129             }
130              
131             =head1 WITH Future::AsyncAwait
132              
133             As of L version 0.32, cross-module integration tests
134             assert that the C correctly works across an C boundary.
135              
136             use Future::AsyncAwait;
137             use Syntax::Keyword::Dynamically;
138              
139             our $var;
140              
141             async sub trial
142             {
143             dynamically $var = "value";
144              
145             await func();
146              
147             say "Var is still $var";
148             }
149              
150             When context-switching between scopes in which a variable is C
151             modified, the value of the variable will be swapped in and out, possibly
152             multiple times if necessary, to ensure the visible value remains as expected.
153              
154             =head1 AUTHOR
155              
156             Paul Evans
157              
158             =cut
159              
160             0x55AA;