Clean-Eval
view release on metacpan or search on metacpan
overload; new 'out' field holds the block's scalar-context return
value on success (block form only - string form never captures a
result, since the body may be defining subs, BEGIN/END blocks, or
otherwise producing nothing meaningful in scalar context).
- 'error' key is now only present on failure; 'out' key is only
present on block-form success. Stringification yields the empty
string on success and the trapped error on failure.
- last_error() is now only updated on failure (successes no longer
reset it). Documented that it remains fragile under DESTROY-time
reentry; capturing the result object at the call site is the
robust path.
- New convenience accessors: ok, out, error.
- Expanded POD: synopsis updated for the new pattern
(if (my $ev = clean_eval {...}) { ... = $ev->out }), new RESULT
OBJECT section, PITFALLS section covering the
my-in-conditional/or-die parsing gotcha, forced scalar context on
block return, string-form lexical visibility, return-from-block
$err = last_error()
Return the result object of the most recent failure produced by
clean_eval or clean_string_eval anywhere in the program, or undef if
no failure has been recorded yet. Successful calls do not reset this
slot. Useful for code paths that discarded the result object or want
to inspect a previous failure after the fact.
Caveat: last_error is a global slot and is subject to the same class
of bug that makes raw $@ fragile. If a DESTROY method (or anything
else running during stack unwind) calls clean_eval or
clean_string_eval and that inner call fails, it will overwrite the
global and the error you actually cared about will be lost.
last_error is a convenience, not a guarantee - the only robust way to
inspect a particular failure is to capture the result object of
clean_eval/clean_string_eval directly at the call site and keep it in
a lexical of your own.
RESULT OBJECT
You can, but you have to be careful. The idiomatic safe pattern looks
like:
my $ok = eval { ...; 1 };
if (!$ok) {
my $err = $@;
...
}
This is correct but verbose, and the ; 1 trailer is easy to forget. The
$@ variable is also famously fragile: destructors that run during stack
unwind can call eval themselves and reset it before you read it.
Localizing $@ the way Clean::Eval does avoids that class of bug
entirely.
PITFALLS
my $ev = clean_eval { ... } or die "$ev" does not work
This looks natural but contains a subtle bug. A lexical introduced by
my is not in scope until the statement that declared it has finished,
- $err = last\_error()
Return the result object of the most recent **failure** produced by
`clean_eval` or `clean_string_eval` anywhere in the program, or `undef`
if no failure has been recorded yet. Successful calls do **not** reset this
slot. Useful for code paths that discarded the result object or want to
inspect a previous failure after the fact.
**Caveat:** `last_error` is a global slot and is subject to the same class
of bug that makes raw `$@` fragile. If a `DESTROY` method (or anything
else running during stack unwind) calls `clean_eval` or
`clean_string_eval` and that inner call fails, it will overwrite the
global and the error you actually cared about will be lost. `last_error`
is a convenience, not a guarantee - the only robust way to inspect a
particular failure is to capture the result object of
`clean_eval`/`clean_string_eval` directly at the call site and keep it
in a lexical of your own.
# RESULT OBJECT
You can, but you have to be careful. The idiomatic safe pattern looks like:
my $ok = eval { ...; 1 };
if (!$ok) {
my $err = $@;
...
}
This is correct but verbose, and the `; 1` trailer is easy to forget. The
`$@` variable is also famously fragile: destructors that run during stack
unwind can call `eval` themselves and reset it before you read it. Localizing
`$@` the way `Clean::Eval` does avoids that class of bug entirely.
# PITFALLS
## `my $ev = clean_eval { ... } or die "$ev"` does not work
This looks natural but contains a subtle bug. A lexical introduced by
`my` is **not** in scope until the statement that declared it has
finished, so the `$ev` referenced by `die "$ev"` is a different,
lib/Clean/Eval.pm view on Meta::CPAN
=item $err = last_error()
Return the result object of the most recent B<failure> produced by
C<clean_eval> or C<clean_string_eval> anywhere in the program, or C<undef>
if no failure has been recorded yet. Successful calls do B<not> reset this
slot. Useful for code paths that discarded the result object or want to
inspect a previous failure after the fact.
B<Caveat:> C<last_error> is a global slot and is subject to the same class
of bug that makes raw C<$@> fragile. If a C<DESTROY> method (or anything
else running during stack unwind) calls C<clean_eval> or
C<clean_string_eval> and that inner call fails, it will overwrite the
global and the error you actually cared about will be lost. C<last_error>
is a convenience, not a guarantee - the only robust way to inspect a
particular failure is to capture the result object of
C<clean_eval>/C<clean_string_eval> directly at the call site and keep it
in a lexical of your own.
=back
lib/Clean/Eval.pm view on Meta::CPAN
You can, but you have to be careful. The idiomatic safe pattern looks like:
my $ok = eval { ...; 1 };
if (!$ok) {
my $err = $@;
...
}
This is correct but verbose, and the C<; 1> trailer is easy to forget. The
C<$@> variable is also famously fragile: destructors that run during stack
unwind can call C<eval> themselves and reset it before you read it. Localizing
C<$@> the way C<Clean::Eval> does avoids that class of bug entirely.
=head1 PITFALLS
=head2 C<my $ev = clean_eval { ... } or die "$ev"> does not work
This looks natural but contains a subtle bug. A lexical introduced by
C<my> is B<not> in scope until the statement that declared it has
finished, so the C<$ev> referenced by C<die "$ev"> is a different,
( run in 1.646 second using v1.01-cache-2.11-cpan-364913b4093 )