Clean-Eval
view release on metacpan or search on metacpan
use Clean::Eval qw/clean_eval clean_string_eval last_error/;
- $ev = clean\_eval { BLOCK }
Run `BLOCK` under `eval`. Always returns a `Clean::Eval` result object
(see ["RESULT OBJECT"](#result-object)). `$@` in the caller's scope is not touched.
On success the block's return value is captured **in scalar context** and
stored in the object's `out` field. Scalar context is forced because the
object is a scalar-context-only carrier - capturing a list there would
require API choices (arrayref? flatten?) that would surprise callers. If
you need list-context results, assign to an outer `my @list` from inside
the block:
my @rows;
my $ev = clean_eval { @rows = fetch_rows() };
die $ev unless $ev;
On failure the `out` key is **not present** on the object and the `error`,
`package`, `file`, and `line` keys are populated instead.
The prototype is `(&)`, so the block form works without a leading `sub`.
- $ev = clean\_string\_eval $STRING
Run `$STRING` as Perl code under `eval`. Always returns a `Clean::Eval`
result object. `$@` in the caller's scope is not touched.
**Unlike the block form, the string form never captures a return value.**
The `out` field is always absent on the result object, even on success.
This is because the body of a string eval is not necessarily a value-
producing expression: it might be defining a subroutine, opening a
`BEGIN`/`INIT`/`END` block, declaring a package, loading a module via
`use`, or otherwise producing something that has no meaningful "scalar
return value" to record. Trying to capture and stash a result in those
cases would just be misleading. If you need a value out of string eval'd
code, write to an outer `our` package variable from inside the string,
or use `clean_eval { eval $string }` and capture the result yourself.
A `#line` directive is prepended to `$STRING` using the caller's filename
and line number, so any error or warning produced by the eval'd code refers
to the source location of the `clean_string_eval` call rather than to an
anonymous eval string.
A trailing `; 1` is also appended to `$STRING`, so you do not need to
remember the usual `eval "...; 1"` success guard - success is recorded on
the result object regardless of what the final statement in `$STRING`
evaluates to. Including the `; 1` yourself is harmless.
The prototype is `($)`, so a single scalar argument is taken.
- $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
Both `clean_eval` and `clean_string_eval` always return a blessed hashref
of class `Clean::Eval`. It overloads boolean and stringification context:
- Boolean context: true on success, false on failure. This is computed from
the `ok` field, so a successful eval whose block legitimately returned a
false value is still distinguishable from a failure.
- String context: the trapped error message on failure (the value `$@` had
inside the eval), or the empty string on success. This lets you write
`die $ev` on a failure without having to dig out a field.
The object is a plain hashref with the following keys. Which keys are
present depends on whether the eval succeeded:
- ok
Always present. `1` on success, `0` on failure.
- out
**Present only on success, and only for the block form.** Holds the block's
return value, taken in scalar context. Absent (the key does not `exists`
at all) on failure, and absent for `clean_string_eval` in all cases.
- error
**Present only on failure.** The trapped error message (string or object,
whatever was `die`'d).
- package
The package the call was made from. Always present.
- file
The file the call was made from. Always present.
- line
The line the call was made from. Always present.
Convenience accessors `ok`, `out`, and `error` return the corresponding
fields. `to_string` returns the same string the `""` overload yields.
# WHY NOT JUST USE `eval`?
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,
package-global `$ev` (which is `undef`):
use Clean::Eval qw/clean_eval/;
# WRONG - $ev inside the die is the package global, not the lexical;
# the die fires (clean_eval returned a false-overloaded object) but
# with an empty message.
my $ev = clean_eval { die "foo" } or die "$ev";
Declare the lexical on its own statement first so it is in scope by the
time the `or die` runs:
use Clean::Eval qw/clean_eval/;
# CORRECT - $ev refers to the lexical in both spots
my $ev;
$ev = clean_eval { die "foo" } or die "$ev";
Or split the check off into its own statement, which has the same effect:
use Clean::Eval qw/clean_eval/;
my $ev = clean_eval { die "foo" };
die "$ev" unless $ev;
The reliable rule: do not reference a `my`-declared variable in the same
statement that declares it. Running with `use warnings` will diagnose
this with `"Name main::ev used only once: possible typo"`.
## The block's return value is taken in scalar context
`clean_eval` stashes the block's return value in `$ev->out`, but
it does so in **scalar context**. A block that returns a list will be
collapsed to the last element (or to the list count, depending on the
expression):
use Clean::Eval qw/clean_eval/;
my $ev = clean_eval { (1, 2, 3) };
# $ev->out is 3, not [1, 2, 3]
If you need a list result, write to an outer lexical from inside the
block:
my @rows;
my $ev = clean_eval { @rows = fetch_rows() };
die $ev unless $ev;
# use @rows here
Scalar context is forced deliberately - the `out` field is a single
( run in 0.935 second using v1.01-cache-2.11-cpan-364913b4093 )