1Hook::LexWrap(3)      User Contributed Perl Documentation     Hook::LexWrap(3)
2
3
4

NAME

6       Hook::LexWrap - Lexically scoped subroutine wrappers
7

VERSION

9       version 0.26
10

SYNOPSIS

12               use Hook::LexWrap;
13
14               sub doit { print "[doit:", caller, "]"; return {my=>"data"} }
15
16               SCOPED: {
17                       wrap doit =>
18                               pre  => sub { print "[pre1: @_]\n" },
19                               post => sub { print "[post1:@_]\n"; $_[1]=9; };
20
21                       my $temporarily = wrap doit =>
22                               post => sub { print "[post2:@_]\n" },
23                               pre  => sub { print "[pre2: @_]\n  "};
24
25                       @args = (1,2,3);
26                       doit(@args);    # pre2->pre1->doit->post1->post2
27               }
28
29               @args = (4,5,6);
30               doit(@args);            # pre1->doit->post1
31

DESCRIPTION

33       Hook::LexWrap allows you to install a pre- or post-wrapper (or both)
34       around an existing subroutine. Unlike other modules that provide this
35       capacity (e.g. Hook::PreAndPost and Hook::WrapSub), Hook::LexWrap
36       implements wrappers in such a way that the standard "caller" function
37       works correctly within the wrapped subroutine.
38
39       To install a prewrappers, you write:
40
41               use Hook::LexWrap;
42
43               wrap 'subroutine_name', pre => \&some_other_sub;
44
45          #or: wrap *subroutine_name,  pre => \&some_other_sub;
46
47       The first argument to "wrap" is a string containing the name of the
48       subroutine to be wrapped (or the typeglob containing it, or a reference
49       to it). The subroutine name may be qualified, and the subroutine must
50       already be defined. The second argument indicates the type of wrapper
51       being applied and must be either 'pre' or 'post'. The third argument
52       must be a reference to a subroutine that implements the wrapper.
53
54       To install a post-wrapper, you write:
55
56               wrap 'subroutine_name', post => \&yet_another_sub;
57
58          #or: wrap *subroutine_name,  post => \&yet_another_sub;
59
60       To install both at once:
61
62               wrap 'subroutine_name',
63                    pre  => \&some_other_sub,
64                    post => \&yet_another_sub;
65
66       or:
67
68               wrap *subroutine_name,
69                    post => \&yet_another_sub,  # order in which wrappers are
70                    pre  => \&some_other_sub;   # specified doesn't matter
71
72       Once they are installed, the pre- and post-wrappers will be called
73       before and after the subroutine itself, and will be passed the same
74       argument list.
75
76       The pre- and post-wrappers and the original subroutine also all see the
77       same (correct!) values from "caller" and "wantarray".
78
79   Short-circuiting and long-circuiting return values
80       The pre- and post-wrappers both receive an extra argument in their @_
81       arrays. That extra argument is appended to the original argument list
82       (i.e. is can always be accessed as $_[-1]) and acts as a place-holder
83       for the original subroutine's return value.
84
85       In a pre-wrapper, $_[-1] is -- for obvious reasons -- "undef". However,
86       $_[-1] may be assigned to in a pre-wrapper, in which case Hook::LexWrap
87       assumes that the original subroutine has been "pre-empted", and that
88       neither it, nor the corresponding post-wrapper, nor any wrappers that
89       were applied before the pre-empting pre-wrapper was installed, need be
90       run. Note that any post-wrappers that were installed after the pre-
91       empting pre-wrapper was installed will still be called before the
92       original subroutine call returns.
93
94       In a post-wrapper, $_[-1] contains the return value produced by the
95       wrapped subroutine. In a scalar return context, this value is the
96       scalar return value. In an list return context, this value is a
97       reference to the array of return values. $_[-1] may be assigned to in a
98       post-wrapper, and this changes the return value accordingly.
99
100       Access to the arguments and return value is useful for implementing
101       techniques such as memoization:
102
103               my %cache;
104               wrap fibonacci =>
105                       pre  => sub { $_[-1] = $cache{$_[0]} if $cache{$_[0]} },
106                       post => sub { $cache{$_[0]} = $_[-1] };
107
108       or for converting arguments and return values in a consistent manner:
109
110               # set_temp expects and returns degrees Fahrenheit,
111               # but we want to use Celsius
112               wrap set_temp =>
113                       pre   => sub { splice @_, 0, 1, $_[0] * 1.8 + 32 },
114                       post  => sub { $_[-1] = ($_[0] - 32) / 1.8 };
115
116   Lexically scoped wrappers
117       Normally, any wrappers installed by "wrap" remain attached to the
118       subroutine until it is undefined. However, it is possible to make
119       specific wrappers lexically bound, so that they operate only until the
120       end of the scope in which they're created (or until some other specific
121       point in the code).
122
123       If "wrap" is called in a non-void context:
124
125               my $lexical = wrap 'sub_name', pre => \&wrapper;
126
127       it returns a special object corresponding to the particular wrapper
128       being placed around the original subroutine. When that object is
129       destroyed -- when its container variable goes out of scope, or when its
130       reference count otherwise falls to zero (e.g. "undef $lexical"), or
131       when it is explicitly destroyed ("$lexical->DESTROY") -- the
132       corresponding wrapper is removed from around the original subroutine.
133       Note, however, that all other wrappers around the subroutine are
134       preserved.
135
136   Anonymous wrappers
137       If the subroutine to be wrapped is passed as a reference (rather than
138       by name or by typeglob), "wrap" does not install the wrappers around
139       the original subroutine. Instead it generates a new subroutine which
140       acts as if it were the original with those wrappers around it.  It then
141       returns a reference to that new subroutine. Only calls to the original
142       through that wrapped reference invoke the wrappers. Direct by-name
143       calls to the original, or calls through another reference, do not.
144
145       If the original is subsequently wrapped by name, the anonymously
146       wrapped subroutine reference does not see those wrappers. In other
147       words, wrappers installed via a subroutine reference are completely
148       independent of those installed via the subroutine's name (or typeglob).
149
150       For example:
151
152               sub original { print "ray" }
153
154               # Wrap anonymously...
155               my $anon_wrapped = wrap \&original, pre => sub { print "do..." };
156
157               # Show effects...
158               original();             # prints "ray"
159               $anon_wrapped->();      # prints "do..ray"
160
161               # Wrap nonymously...
162               wrap *original,
163                       pre  => sub { print "fa.." },
164                       post => sub { print "..mi" };
165
166               # Show effects...
167               original();             #   now prints "fa..ray..mi"
168               $anon_wrapped->();      # still prints "do...ray"
169

DIAGNOSTICS

171       "Can't wrap non-existent subroutine %s"
172           An attempt was made to wrap a subroutine that was not defined at
173           the point of wrapping.
174
175       "'pre' value is not a subroutine reference"
176           The value passed to "wrap" after the 'pre' flag was not a
177           subroutine reference. Typically, someone forgot the "sub" on the
178           anonymous subroutine:
179
180                   wrap 'subname', pre => { your_code_here() };
181
182           and Perl interpreted the last argument as a hash constructor.
183
184       "'post' value is not a subroutine reference"
185           The value passed to "wrap" after the 'post' flag was not a
186           subroutine reference.
187
188       "Uselessly wrapped subroutine reference in void context" (warning only)
189           When the subroutine to be wrapped is passed as a subroutine
190           reference, "wrap" does not install the wrapper around the original,
191           but instead returns a reference to a subroutine which wraps the
192           original (see "Anonymous wrappers").
193
194           However, there's no point in doing this if you don't catch the
195           resulting subroutine reference.
196

BLAME

198       Schwern made me do this (by implying it wasn't possible ;-)
199

SEE ALSO

201       Sub::Prepend
202

BUGS

204       There are undoubtedly serious bugs lurking somewhere in code this funky
205       :-)
206
207       Bug reports and other feedback are most welcome.
208
209       Bugs may be submitted through the RT bug tracker
210       <https://rt.cpan.org/Public/Dist/Display.html?Name=Hook-LexWrap> (or
211       bug-Hook-LexWrap@rt.cpan.org <mailto:bug-Hook-LexWrap@rt.cpan.org>).
212

AUTHOR

214       Damian Conway <damian@conway.org>
215

CONTRIBUTORS

217       •   Karen Etheridge <ether@cpan.org>
218
219       •   Alexandr Ciornii <alexchorny@gmail.com>
220
221       •   Father Chrysostomos <sprout@cpan.org>
222
224       This software is copyright (c) 2001 by Damian Conway.
225
226       This is free software; you can redistribute it and/or modify it under
227       the same terms as the Perl 5 programming language system itself.
228
229
230
231perl v5.36.0                      2022-07-22                  Hook::LexWrap(3)
Impressum