line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
2
|
|
|
2
|
|
23180
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
98
|
|
2
|
2
|
|
|
2
|
|
9
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
146
|
|
3
|
|
|
|
|
|
|
package Hook::LexWrap; |
4
|
|
|
|
|
|
|
# git description: v0.24-8-gd2290ba |
5
|
|
|
|
|
|
|
$Hook::LexWrap::VERSION = '0.25'; |
6
|
|
|
|
|
|
|
# ABSTRACT: Lexically scoped subroutine wrappers |
7
|
|
|
|
|
|
|
|
8
|
2
|
|
|
2
|
|
13
|
use Carp; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
211
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
{ |
11
|
2
|
|
|
2
|
|
12
|
no warnings 'redefine'; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
481
|
|
12
|
|
|
|
|
|
|
*CORE::GLOBAL::caller = sub (;$) { |
13
|
86
|
|
100
|
86
|
|
385
|
my ($height) = ($_[0]||0); |
14
|
86
|
|
|
|
|
94
|
my $i=1; |
15
|
86
|
|
|
|
|
109
|
my $name_cache; |
16
|
86
|
|
|
|
|
137
|
while (1) { |
17
|
402
|
100
|
|
|
|
3154
|
my @caller = CORE::caller($i++) or return; |
18
|
390
|
100
|
|
|
|
884
|
$caller[3] = $name_cache if $name_cache; |
19
|
390
|
100
|
|
|
|
780
|
$name_cache = $caller[0] eq 'Hook::LexWrap' ? $caller[3] : ''; |
20
|
390
|
100
|
100
|
|
|
1980
|
next if $name_cache || $height-- != 0; |
21
|
74
|
100
|
|
|
|
1504
|
return wantarray ? @_ ? @caller : @caller[0..2] : $caller[0]; |
|
|
100
|
|
|
|
|
|
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
}; |
24
|
|
|
|
|
|
|
} |
25
|
|
|
|
|
|
|
|
26
|
2
|
|
|
2
|
|
15
|
sub import { no strict 'refs'; *{caller()."::wrap"} = \&wrap } |
|
2
|
|
|
2
|
|
2
|
|
|
2
|
|
|
|
|
353
|
|
|
2
|
|
|
|
|
18
|
|
|
2
|
|
|
|
|
613
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub wrap (*@) { ## no critic Prototypes |
29
|
28
|
|
|
28
|
1
|
479
|
my ($typeglob, %wrapper) = @_; |
30
|
28
|
100
|
100
|
|
|
207
|
$typeglob = (ref $typeglob || $typeglob =~ /::/) |
31
|
|
|
|
|
|
|
? $typeglob |
32
|
|
|
|
|
|
|
: caller()."::$typeglob"; |
33
|
28
|
|
|
|
|
32
|
my $original; |
34
|
|
|
|
|
|
|
{ |
35
|
2
|
|
|
2
|
|
13
|
no strict 'refs'; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
289
|
|
|
28
|
|
|
|
|
36
|
|
36
|
28
|
|
66
|
|
|
284
|
$original = ref $typeglob eq 'CODE' && $typeglob |
37
|
|
|
|
|
|
|
|| *$typeglob{CODE} |
38
|
|
|
|
|
|
|
|| croak "Can't wrap non-existent subroutine ", $typeglob; |
39
|
|
|
|
|
|
|
} |
40
|
54
|
100
|
|
|
|
331
|
croak "'$_' value is not a subroutine reference" |
41
|
27
|
|
|
|
|
55
|
foreach grep {$wrapper{$_} && ref $wrapper{$_} ne 'CODE'} |
42
|
|
|
|
|
|
|
qw(pre post); |
43
|
2
|
|
|
2
|
|
11
|
no warnings 'redefine'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
926
|
|
44
|
25
|
|
|
|
|
53
|
my ($caller, $unwrap) = *CORE::GLOBAL::caller{CODE}; |
45
|
|
|
|
|
|
|
my $imposter = sub { |
46
|
52
|
100
|
|
52
|
|
223
|
if ($unwrap) { goto &$original } |
|
24
|
|
|
|
|
45
|
|
47
|
28
|
|
|
|
|
37
|
my ($return, $prereturn); |
48
|
28
|
100
|
|
|
|
59
|
if (wantarray) { |
|
|
100
|
|
|
|
|
|
49
|
11
|
|
|
|
|
27
|
$prereturn = $return = []; |
50
|
11
|
100
|
|
|
|
46
|
() = $wrapper{pre}->(@_,$return) if $wrapper{pre}; |
51
|
11
|
100
|
100
|
|
|
142
|
if (ref $return eq 'ARRAY' && $return == $prereturn && !@$return) { |
|
|
|
100
|
|
|
|
|
52
|
7
|
|
|
|
|
16
|
$return = [ &$original ]; |
53
|
7
|
100
|
|
|
|
86
|
() = $wrapper{post}->(@_, $return) |
54
|
|
|
|
|
|
|
if $wrapper{post}; |
55
|
|
|
|
|
|
|
} |
56
|
11
|
100
|
|
|
|
129
|
return ref $return eq 'ARRAY' ? @$return : ($return); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
elsif (defined wantarray) { |
59
|
4
|
|
|
4
|
|
25
|
$return = bless sub {$prereturn=1}, 'Hook::LexWrap::Cleanup'; |
|
4
|
|
|
|
|
31
|
|
60
|
4
|
100
|
|
|
|
20
|
my $dummy = $wrapper{pre}->(@_, $return) if $wrapper{pre}; |
61
|
4
|
100
|
|
|
|
35
|
unless ($prereturn) { |
62
|
3
|
|
|
|
|
7
|
$return = &$original; |
63
|
3
|
50
|
|
|
|
21
|
$dummy = scalar $wrapper{post}->(@_, $return) |
64
|
|
|
|
|
|
|
if $wrapper{post}; |
65
|
|
|
|
|
|
|
} |
66
|
4
|
|
|
|
|
34
|
return $return; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
else { |
69
|
13
|
|
|
13
|
|
68
|
$return = bless sub {$prereturn=1}, 'Hook::LexWrap::Cleanup'; |
|
13
|
|
|
|
|
68
|
|
70
|
13
|
100
|
|
|
|
55
|
$wrapper{pre}->(@_, $return) if $wrapper{pre}; |
71
|
13
|
50
|
|
|
|
63
|
unless ($prereturn) { |
72
|
13
|
|
|
|
|
20
|
&$original; |
73
|
13
|
100
|
|
|
|
124
|
$wrapper{post}->(@_, $return) |
74
|
|
|
|
|
|
|
if $wrapper{post}; |
75
|
|
|
|
|
|
|
} |
76
|
13
|
|
|
|
|
77
|
return; |
77
|
|
|
|
|
|
|
} |
78
|
25
|
|
|
|
|
153
|
}; |
79
|
25
|
100
|
|
|
|
91
|
ref $typeglob eq 'CODE' and return defined wantarray |
|
|
100
|
|
|
|
|
|
80
|
|
|
|
|
|
|
? $imposter |
81
|
|
|
|
|
|
|
: carp "Uselessly wrapped subroutine reference in void context"; |
82
|
|
|
|
|
|
|
{ |
83
|
2
|
|
|
2
|
|
12
|
no strict 'refs'; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
505
|
|
|
23
|
|
|
|
|
25
|
|
84
|
23
|
|
|
|
|
27
|
*{$typeglob} = $imposter; |
|
23
|
|
|
|
|
92
|
|
85
|
|
|
|
|
|
|
} |
86
|
23
|
100
|
|
|
|
82
|
return unless defined wantarray; |
87
|
10
|
|
|
10
|
|
79
|
return bless sub{ $unwrap=1 }, 'Hook::LexWrap::Cleanup'; |
|
10
|
|
|
|
|
41
|
|
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
package Hook::LexWrap::Cleanup; |
91
|
|
|
|
|
|
|
# git description: v0.24-8-gd2290ba |
92
|
|
|
|
|
|
|
$Hook::LexWrap::Cleanup::VERSION = '0.25'; |
93
|
|
|
|
|
|
|
|
94
|
27
|
|
|
27
|
|
918
|
sub DESTROY { $_[0]->() } |
95
|
|
|
|
|
|
|
use overload |
96
|
6
|
|
|
6
|
|
58
|
q{""} => sub { undef }, |
97
|
0
|
|
|
0
|
|
0
|
q{0+} => sub { undef }, |
98
|
0
|
|
|
0
|
|
0
|
q{bool} => sub { undef }, |
99
|
2
|
|
|
2
|
|
3423
|
q{fallback}=>1; #fallback=1 - like no overloading for other operations |
|
2
|
|
|
|
|
2865
|
|
|
2
|
|
|
|
|
29
|
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
1; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
__END__ |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=pod |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=encoding UTF-8 |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head1 NAME |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Hook::LexWrap - Lexically scoped subroutine wrappers |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head1 VERSION |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
version 0.25 |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head1 SYNOPSIS |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
use Hook::LexWrap; |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub doit { print "[doit:", caller, "]"; return {my=>"data"} } |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
SCOPED: { |
124
|
|
|
|
|
|
|
wrap doit => |
125
|
|
|
|
|
|
|
pre => sub { print "[pre1: @_]\n" }, |
126
|
|
|
|
|
|
|
post => sub { print "[post1:@_]\n"; $_[1]=9; }; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
my $temporarily = wrap doit => |
129
|
|
|
|
|
|
|
post => sub { print "[post2:@_]\n" }, |
130
|
|
|
|
|
|
|
pre => sub { print "[pre2: @_]\n "}; |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
@args = (1,2,3); |
133
|
|
|
|
|
|
|
doit(@args); # pre2->pre1->doit->post1->post2 |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
@args = (4,5,6); |
137
|
|
|
|
|
|
|
doit(@args); # pre1->doit->post1 |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head1 DESCRIPTION |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Hook::LexWrap allows you to install a pre- or post-wrapper (or both) |
142
|
|
|
|
|
|
|
around an existing subroutine. Unlike other modules that provide this |
143
|
|
|
|
|
|
|
capacity (e.g. Hook::PreAndPost and Hook::WrapSub), Hook::LexWrap |
144
|
|
|
|
|
|
|
implements wrappers in such a way that the standard C<caller> function |
145
|
|
|
|
|
|
|
works correctly within the wrapped subroutine. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
To install a prewrappers, you write: |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
use Hook::LexWrap; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
wrap 'subroutine_name', pre => \&some_other_sub; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
#or: wrap *subroutine_name, pre => \&some_other_sub; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
The first argument to C<wrap> is a string containing the name of the |
156
|
|
|
|
|
|
|
subroutine to be wrapped (or the typeglob containing it, or a |
157
|
|
|
|
|
|
|
reference to it). The subroutine name may be qualified, and the |
158
|
|
|
|
|
|
|
subroutine must already be defined. The second argument indicates the |
159
|
|
|
|
|
|
|
type of wrapper being applied and must be either C<'pre'> or |
160
|
|
|
|
|
|
|
C<'post'>. The third argument must be a reference to a subroutine that |
161
|
|
|
|
|
|
|
implements the wrapper. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
To install a post-wrapper, you write: |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
wrap 'subroutine_name', post => \&yet_another_sub; |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
#or: wrap *subroutine_name, post => \&yet_another_sub; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
To install both at once: |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
wrap 'subroutine_name', |
172
|
|
|
|
|
|
|
pre => \&some_other_sub, |
173
|
|
|
|
|
|
|
post => \&yet_another_sub; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
or: |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
wrap *subroutine_name, |
178
|
|
|
|
|
|
|
post => \&yet_another_sub, # order in which wrappers are |
179
|
|
|
|
|
|
|
pre => \&some_other_sub; # specified doesn't matter |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Once they are installed, the pre- and post-wrappers will be called before |
182
|
|
|
|
|
|
|
and after the subroutine itself, and will be passed the same argument list. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
The pre- and post-wrappers and the original subroutine also all see the same |
185
|
|
|
|
|
|
|
(correct!) values from C<caller> and C<wantarray>. |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=head2 Short-circuiting and long-circuiting return values |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
The pre- and post-wrappers both receive an extra argument in their @_ |
190
|
|
|
|
|
|
|
arrays. That extra argument is appended to the original argument list |
191
|
|
|
|
|
|
|
(i.e. is can always be accessed as $_[-1]) and acts as a place-holder for |
192
|
|
|
|
|
|
|
the original subroutine's return value. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
In a pre-wrapper, $_[-1] is -- for obvious reasons -- C<undef>. However, |
195
|
|
|
|
|
|
|
$_[-1] may be assigned to in a pre-wrapper, in which case Hook::LexWrap |
196
|
|
|
|
|
|
|
assumes that the original subroutine has been "pre-empted", and that |
197
|
|
|
|
|
|
|
neither it, nor the corresponding post-wrapper, nor any wrappers that |
198
|
|
|
|
|
|
|
were applied I<before> the pre-empting pre-wrapper was installed, need |
199
|
|
|
|
|
|
|
be run. Note that any post-wrappers that were installed after the |
200
|
|
|
|
|
|
|
pre-empting pre-wrapper was installed I<will> still be called before the |
201
|
|
|
|
|
|
|
original subroutine call returns. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
In a post-wrapper, $_[-1] contains the return value produced by the |
204
|
|
|
|
|
|
|
wrapped subroutine. In a scalar return context, this value is the scalar |
205
|
|
|
|
|
|
|
return value. In an list return context, this value is a reference to |
206
|
|
|
|
|
|
|
the array of return values. $_[-1] may be assigned to in a post-wrapper, |
207
|
|
|
|
|
|
|
and this changes the return value accordingly. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Access to the arguments and return value is useful for implementing |
210
|
|
|
|
|
|
|
techniques such as memoization: |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
my %cache; |
213
|
|
|
|
|
|
|
wrap fibonacci => |
214
|
|
|
|
|
|
|
pre => sub { $_[-1] = $cache{$_[0]} if $cache{$_[0]} }, |
215
|
|
|
|
|
|
|
post => sub { $cache{$_[0]} = $_[-1] }; |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
or for converting arguments and return values in a consistent manner: |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# set_temp expects and returns degrees Fahrenheit, |
220
|
|
|
|
|
|
|
# but we want to use Celsius |
221
|
|
|
|
|
|
|
wrap set_temp => |
222
|
|
|
|
|
|
|
pre => sub { splice @_, 0, 1, $_[0] * 1.8 + 32 }, |
223
|
|
|
|
|
|
|
post => sub { $_[-1] = ($_[0] - 32) / 1.8 }; |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=head2 Lexically scoped wrappers |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
Normally, any wrappers installed by C<wrap> remain attached to the |
228
|
|
|
|
|
|
|
subroutine until it is undefined. However, it is possible to make |
229
|
|
|
|
|
|
|
specific wrappers lexically bound, so that they operate only until |
230
|
|
|
|
|
|
|
the end of the scope in which they're created (or until some other |
231
|
|
|
|
|
|
|
specific point in the code). |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
If C<wrap> is called in a I<non-void> context: |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
my $lexical = wrap 'sub_name', pre => \&wrapper; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
it returns a special object corresponding to the particular wrapper being |
238
|
|
|
|
|
|
|
placed around the original subroutine. When that object is destroyed |
239
|
|
|
|
|
|
|
-- when its container variable goes out of scope, or when its |
240
|
|
|
|
|
|
|
reference count otherwise falls to zero (e.g. C<undef $lexical>), or |
241
|
|
|
|
|
|
|
when it is explicitly destroyed (C<$lexical-E<gt>DESTROY>) -- |
242
|
|
|
|
|
|
|
the corresponding wrapper is removed from around |
243
|
|
|
|
|
|
|
the original subroutine. Note, however, that all other wrappers around the |
244
|
|
|
|
|
|
|
subroutine are preserved. |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=head2 Anonymous wrappers |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
If the subroutine to be wrapped is passed as a reference (rather than by name |
249
|
|
|
|
|
|
|
or by typeglob), C<wrap> does not install the wrappers around the |
250
|
|
|
|
|
|
|
original subroutine. Instead it generates a new subroutine which acts |
251
|
|
|
|
|
|
|
as if it were the original with those wrappers around it. |
252
|
|
|
|
|
|
|
It then returns a reference to that new subroutine. Only calls to the original |
253
|
|
|
|
|
|
|
through that wrapped reference invoke the wrappers. Direct by-name calls to |
254
|
|
|
|
|
|
|
the original, or calls through another reference, do not. |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
If the original is subsequently wrapped by name, the anonymously wrapped |
257
|
|
|
|
|
|
|
subroutine reference does not see those wrappers. In other words, |
258
|
|
|
|
|
|
|
wrappers installed via a subroutine reference are completely independent |
259
|
|
|
|
|
|
|
of those installed via the subroutine's name (or typeglob). |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
For example: |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub original { print "ray" } |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# Wrap anonymously... |
266
|
|
|
|
|
|
|
my $anon_wrapped = wrap \&original, pre => sub { print "do..." }; |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
# Show effects... |
269
|
|
|
|
|
|
|
original(); # prints "ray" |
270
|
|
|
|
|
|
|
$anon_wrapped->(); # prints "do..ray" |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# Wrap nonymously... |
273
|
|
|
|
|
|
|
wrap *original, |
274
|
|
|
|
|
|
|
pre => sub { print "fa.." }, |
275
|
|
|
|
|
|
|
post => sub { print "..mi" }; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Show effects... |
278
|
|
|
|
|
|
|
original(); # now prints "fa..ray..mi" |
279
|
|
|
|
|
|
|
$anon_wrapped->(); # still prints "do...ray" |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head1 DIAGNOSTICS |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=over |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=item C<Can't wrap non-existent subroutine %s> |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
An attempt was made to wrap a subroutine that was not defined at the |
288
|
|
|
|
|
|
|
point of wrapping. |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=item C<'pre' value is not a subroutine reference> |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
The value passed to C<wrap> after the C<'pre'> flag was not |
293
|
|
|
|
|
|
|
a subroutine reference. Typically, someone forgot the C<sub> on |
294
|
|
|
|
|
|
|
the anonymous subroutine: |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
wrap 'subname', pre => { your_code_here() }; |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
and Perl interpreted the last argument as a hash constructor. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=item C<'post' value is not a subroutine reference> |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
The value passed to C<wrap> after the C<'post'> flag was not |
303
|
|
|
|
|
|
|
a subroutine reference. |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=item C<Uselessly wrapped subroutine reference in void context> (warning only) |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
When the subroutine to be wrapped is passed as a subroutine reference, |
308
|
|
|
|
|
|
|
C<wrap> does not install the wrapper around the original, but instead |
309
|
|
|
|
|
|
|
returns a reference to a subroutine which wraps the original |
310
|
|
|
|
|
|
|
(see L<Anonymous wrappers>). |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
However, there's no point in doing this if you don't catch the resulting |
313
|
|
|
|
|
|
|
subroutine reference. |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=back |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head1 BLAME |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Schwern made me do this (by implying it wasn't possible ;-) |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=head1 BUGS |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
There are undoubtedly serious bugs lurking somewhere in code this funky :-) |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
Bug reports and other feedback are most welcome. |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head1 SEE ALSO |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Sub::Prepend |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 AUTHOR |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Damian Conway <damian@conway.org> |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
This software is copyright (c) 2001 by Damian Conway. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
340
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=head1 CONTRIBUTORS |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
=for stopwords Alexandr Ciornii Karen Etheridge Father Chrysostomos |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=over 4 |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=item * |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
Alexandr Ciornii <alexchorny@gmail.com> |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=item * |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
Karen Etheridge <ether@cpan.org> |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=item * |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
Father Chrysostomos <sprout@cpan.org> |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=back |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=cut |