1Exception::Class::TryCaUtscehr(3C)ontributed Perl DocumeEnxtcaetpitoinon::Class::TryCatch(3)
2
3
4

NAME

6       Exception::Class::TryCatch - Syntactic try/catch sugar for use with
7       Exception::Class
8

VERSION

10       version 1.13
11

SYNOPSIS

13            use Exception::Class::TryCatch;
14
15            # simple usage of catch()
16
17            eval { Exception::Class::Base->throw('error') };
18            catch my $err and warn $err->error;
19
20            # catching only certain types or else rethrowing
21
22            eval { Exception::Class::Base::SubClass->throw('error') };
23            catch( my $err, ['Exception::Class::Base', 'Other::Exception'] )
24                and warn $err->error;
25
26            # catching and handling different types of errors
27
28            eval { Exception::Class::Base->throw('error') };
29            if ( catch my $err ) {
30                $err->isa('this') and do { handle_this($err) };
31                $err->isa('that') and do { handle_that($err) };
32            }
33
34            # use "try eval" to push exceptions onto a stack to catch later
35
36            try eval {
37                Exception::Class::Base->throw('error')
38            };
39            do {
40                # cleanup that might use "try/catch" again
41            };
42            catch my $err; # catches a matching "try"
43

DESCRIPTION

45       Exception::Class::TryCatch provides syntactic sugar for use with
46       Exception::Class using the familiar keywords "try" and "catch".  Its
47       primary objective is to allow users to avoid dealing directly with $@
48       by ensuring that any exceptions caught in an "eval" are captured as
49       Exception::Class objects, whether they were thrown objects to begin
50       with or whether the error resulted from "die".  This means that users
51       may immediately use "isa" and various Exception::Class methods to
52       process the exception.
53
54       In addition, this module provides for a method to push errors onto a
55       hidden error stack immediately after an "eval" so that cleanup code or
56       other error handling may also call "eval" without the original error in
57       $@ being lost.
58
59       Inspiration for this module is due in part to Dave Rolsky's article
60       "Exception Handling in Perl With Exception::Class" in The Perl Journal
61       (Rolsky 2004).
62
63       The "try/catch" syntax used in this module does not use code reference
64       prototypes the way the Error.pm module does, but simply provides some
65       helpful functionality when used in combination with "eval".  As a
66       result, it avoids the complexity and dangers involving nested closures
67       and memory leaks inherent in Error.pm (Perrin 2003).
68
69       Rolsky (2004) notes that these memory leaks may not occur in recent
70       versions of Perl, but the approach used in Exception::Class::TryCatch
71       should be safe for all versions of Perl as it leaves all code execution
72       to the "eval" in the current scope, avoiding closures altogether.
73

USAGE

75   "catch"
76            # zero argument form
77            my $err = catch;
78
79            # one argument forms
80            catch my $err;
81            my $err = catch( [ 'Exception::Type', 'Exception::Other::Type' ] );
82
83            # two argument form
84            catch my $err, [ 'Exception::Type', 'Exception::Other::Type' ];
85
86       Returns an "Exception::Class::Base" object (or an object which is a
87       subclass of it) if an exception has been caught by "eval".  If no
88       exception was thrown, it returns "undef" in scalar context and an empty
89       list in list context.   The exception is either popped from a hidden
90       error stack (see "try") or, if the stack is empty, taken from the
91       current value of $@.
92
93       If the exception is not an "Exception::Class::Base" object (or subclass
94       object), an "Exception::Class::Base" object will be created using the
95       string contents of the exception.  This means that calls to "die" will
96       be wrapped and may be treated as exception objects.  Other objects
97       caught will be stringified and wrapped likewise.  Such wrapping will
98       likely result in confusing stack traces and the like, so any methods
99       other than "error" used on "Exception::Class::Base" objects caught
100       should be used with caution.
101
102       "catch" is prototyped to take up to two optional scalar arguments.  The
103       single argument form has two variations.
104
105       •   If the argument is a reference to an array, any exception caught
106           that is not of the same type (or a subtype) of one of the classes
107           listed in the array will be rethrown.
108
109       •   If the argument is not a reference to an array, "catch" will set
110           the argument to the same value that is returned.  This allows for
111           the "catch my $err" idiom without parentheses.
112
113       In the two-argument form, the first argument is set to the same value
114       as is returned.  The second argument must be an array reference and is
115       handled the same as as for the single argument version with an array
116       reference, as given above.
117
118   "caught" (DEPRECATED)
119       "caught" is a synonym for "catch" for syntactic convenience.
120
121       NOTE: Exception::Class version 1.21 added a "caught" method of its own.
122       It provides somewhat similar functionality to this subroutine, but with
123       very different semantics.  As this class is intended to work closely
124       with Exception::Class, the existence of a subroutine and a method with
125       the same name is liable to cause confusion and this method is
126       deprecated and may be removed in future releases of
127       Exception::Class::TryCatch.
128
129       This method is no longer exported by default.
130
131   "try"
132            # void context
133            try eval {
134              # dangerous code
135            };
136            do {
137              # cleanup code can use try/catch
138            };
139            catch my $err;
140
141            # scalar context
142            $rv = try eval { return $scalar };
143
144            # list context
145            @rv = try [ eval { return @array } ];
146
147       Pushes the current error ($@) onto a hidden error stack for later use
148       by "catch".  "try" uses a prototype that expects a single scalar so
149       that it can be used with eval without parentheses.  As "eval { BLOCK }"
150       is an argument to try, it will be evaluated just prior to "try",
151       ensuring that "try" captures the correct error status.  "try" does not
152       itself handle any errors -- it merely records the results of "eval".
153       "try { BLOCK }" will be interpreted as passing a hash reference and
154       will (probably) not compile. (And if it does, it will result in very
155       unexpected behavior.)
156
157       Since "try" requires a single argument, "eval" will normally be called
158       in scalar context.  To use "eval" in list context with "try", put the
159       call to "eval" in an anonymous array:
160
161          @rv = try [ eval {return @array} ];
162
163       When "try" is called in list context, if the argument to "try" is an
164       array reference, "try" will dereference the array and return the
165       resulting list.
166
167       In scalar context, "try" passes through the scalar value returned by
168       "eval" without modifications -- even if that is an array reference.
169
170          $rv = try eval { return $scalar };
171          $rv = try eval { return [ qw( anonymous array ) ] };
172
173       Of course, if the eval throws an exception, "eval" and thus "try" will
174       return undef.
175
176       "try" must always be properly bracketed with a matching "catch" or
177       unexpected behavior may result when "catch" pops the error off of the
178       stack.  "try" executes right after its "eval", so inconsistent usage of
179       "try" like the following will work as expected:
180
181            try eval {
182                eval { die "inner" };
183                catch my $inner_err
184                die "outer" if $inner_err;
185            };
186            catch my $outer_err;
187            # handle $outer_err;
188
189       However, the following code is a problem:
190
191            # BAD EXAMPLE
192            try eval {
193                try eval { die "inner" };
194                die $@ if $@;
195            };
196            catch my $outer_err;
197            # handle $outer_err;
198
199       This code will appear to run correctly, but "catch" gets the exception
200       from the inner "try", not the outer one, and there will still be an
201       exception on the error stack which will be caught by the next "catch"
202       in the program, causing unexpected (and likely hard to track) behavior.
203
204       In short, if you use "try", you must have a matching "catch".  The
205       problem code above should be rewritten as:
206
207            try eval {
208                try eval { die "inner" };
209                catch my $inner_err;
210                $inner_err->rethrow if $inner_err;
211            };
212            catch my $outer_err;
213            # handle $outer_err;
214

REFERENCES

216       1.  perrin. (2003), "Re: Re2: Learning how to use the Error module by
217           example", (perlmonks.org), Available:
218           http://www.perlmonks.org/index.pl?node_id=278900 (Accessed
219           September 8, 2004).
220
221       2.  Rolsky, D. (2004), "Exception Handling in Perl with
222           Exception::Class", The Perl Journal, vol. 8, no. 7, pp. 9-13
223

SEE ALSO

225       •   Exception::Class
226
227       •   Error -- but see (Perrin 2003) before using
228

SUPPORT

230   Bugs / Feature Requests
231       Please report any bugs or feature requests through the issue tracker at
232       <https://github.com/dagolden/Exception-Class-TryCatch/issues>.  You
233       will be notified automatically of any progress on your issue.
234
235   Source Code
236       This is open source software.  The code repository is available for
237       public review and contribution under the terms of the license.
238
239       <https://github.com/dagolden/Exception-Class-TryCatch>
240
241         git clone https://github.com/dagolden/Exception-Class-TryCatch.git
242

AUTHOR

244       David Golden <dagolden@cpan.org>
245
247       This software is Copyright (c) 2014 by David Golden.
248
249       This is free software, licensed under:
250
251         The Apache License, Version 2.0, January 2004
252
253
254
255perl v5.32.1                      2021-01-27     Exception::Class::TryCatch(3)
Impressum