kiz has asked for the wisdom of the Perl Monks concerning the following question:

So what does eval actually do, and actually trap?

Considering this code:

eval { $content = $self->web_fetch( { raw => 1 } ); }; # a $content = eval { $self->web_fetch( { raw => 1 } ); }; # b if ($EVAL_ERROR) { # $@ return $self->do_harvest_return(undef); }

(We can assume that web_fetch and do_harvest_return are methods written by us, and contain some carp and croak statements)

#1 There's an implicit statement that eval does not return true or false on it's own... the implication is that it doesn't return anything (unlike, for example, print - which returns true on a successfull print)

I assume $EVAL_ERROR will contain the first croak (or other fatal) error from the web_fetch method in both a and b

.... but what about the difference between a and b - doesn't a also report if the assignment to $content fails? - if so, why does best practice suggest b? (2nd Edition, P 277)

#2 Is there a preferred style for using eval?



-- Ian Stuart
A man depriving some poor village, somewhere, of a first-class idiot.

Replies are listed 'Best First'.
Re: What does eval actually do?
by Corion (Pope) on Oct 28, 2015 at 10:50 UTC

    My preferred style of using eval is

    my $content; my $ok = eval { $content = $self->web_fetch( ... ); 1 }; if( ! $ok ) { my $err = $@; ... };

    This avoids needing to think about whether there was an error or the assignment returned a false value. I think that Try::Tiny provides some syntactic sugar for this approach.

Re: What does eval actually do?
by Anonymous Monk on Oct 28, 2015 at 12:02 UTC
    There's an implicit statement that eval does not return true or false on it's own... the implication is that it doesn't return anything

    Have you read all of the documentation?

    In both forms, the value returned is the value of the last expression evaluated inside the mini-program ... If there is a syntax error or runtime error, or a die statement is executed, eval returns undef in scalar context or an empty list in list context, and $@ is set to the error message.

    Also, there are several issues with $@ (some have been addressed in recent versions of Perl), for example the Try::Tiny documentation section "Background" contains a good description. Unfortunately, there are lots of examples on the net that still use the problematic form eval { ... }; if ($@) ...

    That's the background of Corion's suggestion of having the eval block return a true value on success and checking that using my $ok = eval { ...; 1 }; if (!$ok) ... (which could also be written as eval { ...; 1 } or die ... for example), or Try::Tiny. Those are also my preferred style.

A reply falls below the community's threshold of quality. You may see it by logging in.