NAME

Clean::Eval - Run code under eval without leaking $@ and get a rich error object back on failure.

DESCRIPTION

Perl's built-in eval is the standard way to trap exceptions, but it has two long-standing ergonomic problems:

Clean::Eval wraps eval in a way that avoids both problems. It localizes $@ so the caller's copy is never touched, returns a true value on success, and returns an overloaded error object on failure. The error object stringifies to the trapped error and is always false in boolean context, so a single if check is enough to distinguish success from failure regardless of what the wrapped code returned.

Both a block form (clean_eval { ... }) and a string form (clean_string_eval $code) are provided. The string form rewrites #line information so that any error reports the file and line of the caller, not an anonymous (eval N).

SYNOPSIS

use Clean::Eval qw/clean_eval clean_string_eval last_error/;

# Block form
if (my $ret = clean_eval { do_something_risky() }) {
    # success path - $ret is a true value (1)
}
else {
    # failure path - $ret is the error object
    warn "Failed: $ret\n";          # stringifies to error message
    warn "  at $ret->{file} line $ret->{line}\n";
}

# String form (compiles at runtime). No need to add a trailing
# "; 1" - it is appended for you so the success path is unambiguous.
my $ret = clean_string_eval 'use SomeOptionalModule';
unless ($ret) {
    warn "Optional dep missing: $ret\n";
}

# Retrieve the most recent error from anywhere
my $last = last_error();

EXPORTS

Nothing is exported by default. The three functions below may be imported individually using Importer-style syntax:

use Clean::Eval qw/clean_eval clean_string_eval last_error/;

ERROR OBJECT

On failure both clean_eval and clean_string_eval return a blessed hashref of class Clean::Eval. It overloads stringification and boolean context:

The object is a plain hashref with the following keys:

An additional to_string method is provided that returns the error message; it is equivalent to stringifying the object.

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.

SEE ALSO

Try::Tiny, Syntax::Keyword::Try, Feature::Compat::Try.

SOURCE

The source code repository for Clean-Eval can be found at https://github.com/exodist/Clean-Eval/.

MAINTAINERS

AUTHORS

COPYRIGHT

Copyright 2026 Chad Granum exodist7@gmail.com.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See http://dev.perl.org/licenses/