Clean-Eval

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

      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

README  view on Meta::CPAN


    $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

README  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 ; 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,

README.md  view on Meta::CPAN


- $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

README.md  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 `; 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 )