Clean-Eval

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

    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 )