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.21 of Hook::LexWrap, released
10 November 6, 2008.
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 The pre- and post-wrappers both receive an extra argument in their @_
82 arrays. That extra argument is appended to the original argument list
83 (i.e. is can always be accessed as $_[-1]) and acts as a place-holder
84 for the original subroutine's return value.
85
86 In a pre-wrapper, $_[-1] is -- for obvious reasons -- "undef". However,
87 $_[-1] may be assigned to in a pre-wrapper, in which case Hook::LexWrap
88 assumes that the original subroutine has been "pre-empted", and that
89 neither it, nor the corresponding post-wrapper, nor any wrappers that
90 were applied before the pre-empting pre-wrapper was installed, need be
91 run. Note that any post-wrappers that were installed after the pre-
92 empting pre-wrapper was installed will still be called before the
93 original subroutine call returns.
94
95 In a post-wrapper, $_[-1] contains the return value produced by the
96 wrapped subroutine. In a scalar return context, this value is the
97 scalar return value. In an list return context, this value is a
98 reference to the array of return values. $_[-1] may be assigned to in a
99 post-wrapper, and this changes the return value accordingly.
100
101 Access to the arguments and return value is useful for implementing
102 techniques such as memoization:
103
104 my %cache;
105 wrap fibonacci,
106 pre => sub { $_[-1] = $cache{$_[0]} if $cache{$_[0]} },
107 post => sub { $cache{$_[0]} = $_[-1] };
108
109 or for converting arguments and return values in a consistent manner:
110
111 # set_temp expects and returns degrees Fahrenheit,
112 # but we want to use Celsius
113 wrap set_temp,
114 pre => sub { splice @_, 0, 1, $_[0] * 1.8 + 32 },
115 post => sub { $_[-1] = ($_[0] - 32) / 1.8 };
116
117 Lexically scoped wrappers
118 Normally, any wrappers installed by "wrap" remain attached to the
119 subroutine until it is undefined. However, it is possible to make
120 specific wrappers lexically bound, so that they operate only until the
121 end of the scope in which they're created (or until some other specific
122 point in the code).
123
124 If "wrap" is called in a non-void context:
125
126 my $lexical = wrap 'sub_name', pre => \&wrapper;
127
128 it returns a special object corresponding to the particular wrapper
129 being placed around the original subroutine. When that object is
130 destroyed -- when its container variable goes out of scope, or when its
131 reference count otherwise falls to zero (e.g. "undef $lexical"), or
132 when it is explicitly destroyed ("$lexical->DESTROY") -- the
133 corresponding wrapper is removed from around the original subroutine.
134 Note, however, that all other wrappers around the subroutine are
135 preserved.
136
137 Anonymous wrappers
138 If the subroutine to be wrapped is passed as a reference (rather than
139 by name or by typeglob), "wrap" does not install the wrappers around
140 the original subroutine. Instead it generates a new subroutine which
141 acts as if it were the original with those wrappers around it. It then
142 returns a reference to that new subroutine. Only calls to the original
143 through that wrapped reference invoke the wrappers. Direct by-name
144 calls to the original, or calls through another reference, do not.
145
146 If the original is subsequently wrapped by name, the anonymously
147 wrapped subroutine reference does not see those wrappers. In other
148 words, wrappers installed via a subroutine reference are completely
149 independent of those installed via the subroutine's name (or typeglob).
150
151 For example:
152
153 sub original { print "ray" }
154
155 # Wrap anonymously...
156 my $anon_wrapped = wrap \&original, pre => sub { print "do..." };
157
158 # Show effects...
159 original(); # prints "ray"
160 $anon_wrapped->(); # prints "do..ray"
161
162 # Wrap nonymously...
163 wrap *original,
164 pre => sub { print "fa.." },
165 post => sub { print "..mi" };
166
167 # Show effects...
168 original(); # now prints "fa..ray..mi"
169 $anon_wrapped->(); # still prints "do...ray"
170
172 "Can't wrap non-existent subroutine %s"
173 An attempt was made to wrap a subroutine that was not defined at
174 the point of wrapping.
175
176 "'pre' value is not a subroutine reference"
177 The value passed to "wrap" after the 'pre' flag was not a
178 subroutine reference. Typically, someone forgot the "sub" on the
179 anonymous subroutine:
180
181 wrap 'subname', pre => { your_code_here() };
182
183 and Perl interpreted the last argument as a hash constructor.
184
185 "'post' value is not a subroutine reference"
186 The value passed to "wrap" after the 'post' flag was not a
187 subroutine reference.
188
189 "Uselessly wrapped subroutine reference in void context" (warning only)
190 When the subroutine to be wrapped is passed as a subroutine
191 reference, "wrap" does not install the wrapper around the original,
192 but instead returns a reference to a subroutine which wraps the
193 original (see "Anonymous wrappers").
194
195 However, there's no point in doing this if you don't catch the
196 resulting subroutine reference.
197
199 Damian Conway (damian@conway.org)
200
202 Schwern made me do this (by implying it wasn't possible ;-)
203
205 There are undoubtedly serious bugs lurking somewhere in code this funky
206 :-)
207
208 Bug reports and other feedback are most welcome.
209
211 Sub::Prepend
212
214 Copyright (c) 2001, Damian Conway. All Rights Reserved.
215 This module is free software. It may be used, redistributed
216 and/or modified under the same terms as Perl itself.
217
218
219
220perl v5.10.1 2008-12-18 Hook::LexWrap(3)