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

NAME

6       Hook::LexWrap - Lexically scoped subroutine wrappers
7

VERSION

9       This document describes version 0.20 of Hook::LexWrap, released October
10       1, 2001.
11

SYNOPSIS

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

DESCRIPTION

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

DIAGNOSTICS

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

AUTHOR

201       Damian Conway (damian@conway.org)
202

BLAME

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

BUGS

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)
Impressum