1Hook::LexWrap(3) User Contributed Perl Documentation Hook::LexWrap(3)
2
3
4
6 Hook::LexWrap - Lexically scoped subroutine wrappers
7
9 This document describes version 0.20 of Hook::LexWrap, released October
10 1, 2001.
11
13 use Hook::LexWrap;
14
15 sub doit { print "[doit:", caller, "]"; return {my=>"data"} }
16
17 SCOPED: {
18 wrap doit,
19 pre => sub { print "[pre1: @_]\n" },
20 post => sub { print "[post1:@_]\n"; $_[1]=9; };
21
22 my $temporarily = wrap doit,
23 post => sub { print "[post2:@_]\n" },
24 pre => sub { print "[pre2: @_]\n "};
25
26 @args = (1,2,3);
27 doit(@args); # pre2->pre1->doit->post1->post2
28 }
29
30 @args = (4,5,6);
31 doit(@args); # pre1->doit->post1
32
34 Hook::LexWrap allows you to install a pre- or post-wrapper (or both)
35 around an existing subroutine. Unlike other modules that provide this
36 capacity (e.g. Hook::PreAndPost and Hook::WrapSub), Hook::LexWrap
37 implements wrappers in such a way that the standard "caller" function
38 works correctly within the wrapped subroutine.
39
40 To install a prewrappers, you write:
41
42 use Hook::LexWrap;
43
44 wrap 'subroutine_name', pre => \&some_other_sub;
45
46 #or: wrap *subroutine_name, pre => \&some_other_sub;
47
48 The first argument to "wrap" is a string containing the name of the
49 subroutine to be wrapped (or the typeglob containing it, or a reference
50 to it). The subroutine name may be qualified, and the subroutine must
51 already be defined. The second argument indicates the type of wrapper
52 being applied and must be either 'pre' or 'post'. The third argument
53 must be a reference to a subroutine that implements the wrapper.
54
55 To install a post-wrapper, you write:
56
57 wrap 'subroutine_name', post => \&yet_another_sub;
58
59 #or: wrap *subroutine_name, post => \&yet_another_sub;
60
61 To install both at once:
62
63 wrap 'subroutine_name',
64 pre => \&some_other_sub,
65 post => \&yet_another_sub;
66
67 or:
68
69 wrap *subroutine_name,
70 post => \&yet_another_sub, # order in which wrappers are
71 pre => \&some_other_sub; # specified doesn't matter
72
73 Once they are installed, the pre- and post-wrappers will be called
74 before and after the subroutine itself, and will be passed the same
75 argument list.
76
77 The pre- and post-wrappers and the original subroutine also all see the
78 same (correct!) values from "caller" and "wantarray".
79
80 Short-circuiting and long-circuiting return values
81
82 The pre- and post-wrappers both receive an extra argument in their @_
83 arrays. That extra argument is appended to the original argument list
84 (i.e. is can always be accessed as $_[-1]) and acts as a place-holder
85 for the original subroutine's return value.
86
87 In a pre-wrapper, $_[-1] is -- for obvious reasons -- "undef". However,
88 $_[-1] may be assigned to in a pre-wrapper, in which case Hook::LexWrap
89 assumes that the original subroutine has been "pre-empted", and that
90 neither it, nor the corresponding post-wrapper, nor any wrappers that
91 were applied before the pre-empting pre-wrapper was installed, need be
92 run. Note that any post-wrappers that were installed after the pre-
93 empting pre-wrapper was installed will still be called before the orig‐
94 inal subroutine call returns.
95
96 In a post-wrapper, $_[-1] contains the return value produced by the
97 wrapped subroutine. In a scalar return context, this value is the
98 scalar return value. In an list return context, this value is a refer‐
99 ence to the array of return values. $_[-1] may be assigned to in a
100 post-wrapper, and this changes the return value accordingly.
101
102 Access to the arguments and return value is useful for implementing
103 techniques such as memoization:
104
105 my %cache;
106 wrap fibonacci,
107 pre => sub { $_[-1] = $cache{$_[0]} if $cache{$_[0]} },
108 post => sub { $cache{$_[0]} = $_[-1] };
109
110 or for converting arguments and return values in a consistent manner:
111
112 # set_temp expects and returns degrees Fahrenheit,
113 # but we want to use Celsius
114 wrap set_temp,
115 pre => sub { splice @_, 0, 1, $_[0] * 1.8 + 32 },
116 post => sub { $_[-1] = ($_[0] - 32) / 1.8 };
117
118 Lexically scoped wrappers
119
120 Normally, any wrappers installed by "wrap" remain attached to the sub‐
121 routine until it is undefined. However, it is possible to make specific
122 wrappers lexically bound, so that they operate only until the end of
123 the scope in which they're created (or until some other specific point
124 in the code).
125
126 If "wrap" is called in a non-void context:
127
128 my $lexical = wrap 'sub_name', pre => \&wrapper;
129
130 it returns a special object corresponding to the particular wrapper
131 being placed around the original subroutine. When that object is
132 destroyed -- when its container variable goes out of scope, or when its
133 reference count otherwise falls to zero (e.g. "undef $lexical"), or
134 when it is explicitly destroyed ("$lexical->DESTROY") -- the corre‐
135 sponding wrapper is removed from around the original subroutine. Note,
136 however, that all other wrappers around the subroutine are preserved.
137
138 Anonymous wrappers
139
140 If the subroutine to be wrapped is passed as a reference (rather than
141 by name or by typeglob), "wrap" does not install the wrappers around
142 the original subroutine. Instead it generates a new subroutine which
143 acts as if it were the original with those wrappers around it. It then
144 returns a reference to that new subroutine. Only calls to the original
145 through that wrapped reference invoke the wrappers. Direct by-name
146 calls to the original, or calls through another reference, do not.
147
148 If the original is subsequently wrapped by name, the anonymously
149 wrapped subroutine reference does not see those wrappers. In other
150 words, wrappers installed via a subroutine reference are completely
151 independent of those installed via the subroutine's name (or typeglob).
152
153 For example:
154
155 sub original { print "ray" }
156
157 # Wrap anonymously...
158 my $anon_wrapped = wrap \&original, pre => sub { print "do..." };
159
160 # Show effects...
161 original(); # prints "ray"
162 $anon_wrapped->(); # prints "do..ray"
163
164 # Wrap nonymously...
165 wrap *original,
166 pre => sub { print "fa.." },
167 post => sub { print "..mi" };
168
169 # Show effects...
170 original(); # now prints "fa..ray..mi"
171 $anon_wrapped->(); # still prints "do...ray"
172
174 "Can't wrap non-existent subroutine %s"
175 An attempt was made to wrap a subroutine that was not defined at
176 the point of wrapping.
177
178 "'pre' value is not a subroutine reference"
179 The value passed to "wrap" after the 'pre' flag was not a subrou‐
180 tine reference. Typically, someone forgot the "sub" on the anony‐
181 mous subroutine:
182
183 wrap 'subname', pre => { your_code_here() };
184
185 and Perl interpreted the last argument as a hash constructor.
186
187 "'post' value is not a subroutine reference"
188 The value passed to "wrap" after the 'post' flag was not a subrou‐
189 tine reference.
190
191 "Uselessly wrapped subroutine reference in void context" (warning only)
192 When the subroutine to be wrapped is passed as a subroutine refer‐
193 ence, "wrap" does not install the wrapper around the original, but
194 instead returns a reference to a subroutine which wraps the origi‐
195 nal (see "Anonymous wrappers").
196
197 However, there's no point in doing this if you don't catch the
198 resulting subroutine reference.
199
201 Damian Conway (damian@conway.org)
202
204 Schwern made me do this (by implying it wasn't possible ;-)
205
207 There are undoubtedly serious bugs lurking somewhere in code this funky
208 :-)
209
210 Bug reports and other feedback are most welcome.
211
213 Copyright (c) 2001, Damian Conway. All Rights Reserved.
214 This module is free software. It may be used, redistributed
215 and/or modified under the same terms as Perl itself.
216
217
218
219perl v5.8.8 2001-10-01 Hook::LexWrap(3)