eval and Try::Tiny


T

Tim McDaniel

Miscellaneous neepery on the subject of eval and Try::Tiny.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#! /usr/bin/perl
use strict;
use warnings;
use Try::Tiny;
use Data::Dumper;

my $eval = eval {die 'In eval'};
print Data::Dumper->Dump([$eval, [email protected]], [qw[eval error]]), "\n=====\n";

my $error = '';
my $try = try { die 'In try with naive catch' } catch { $error = $_; };
print Data::Dumper->Dump([$try, $error], [qw[try error]]), "\n=====\n";

$try = try { die 'In try with larger catch' } catch { $error = $_; return };
print Data::Dumper->Dump([$try, $error], [qw[try error]]), "\n";
exit 0;

Output:

$ perl local/test/052.pl
$eval = undef;
$error = 'In eval at local/test/052.pl line 7.
';

=====
$try = 'In try with naive catch at local/test/052.pl line 11.
';
$error = 'In try with naive catch at local/test/052.pl line 11.
';

=====
$try = undef;
$error = 'In try with larger catch at local/test/052.pl line 14.
';


Indeed, checking the code as of 5.8.8, and the most recent source
under http://search.cpan.org/~doy/Try-Tiny-0.11/lib/Try/Tiny.pm, catch
is invoked with

for ($error) {
return $catch->($error);
}

(I think it's stupid as all hell, but whatever.) So I think I can
replace

some_lhs = eval { body };
# uses of [email protected]

with

my $error;
some_lhs = try { body } catch { $error = $_; return };
# uses of $error

Is that right?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I've run across cases of

eval string_value

that I want to replace. Since the code for Try::Tiny localizes [email protected],
I think I can get away with

try { eval string_value; die [email protected] if [email protected] } catch { $error = $_; return }

Anyone see a problem with that?
 
Ad

Advertisements

R

Rainer Weikusat

Miscellaneous neepery on the subject of eval and Try::Tiny.
[...]


my $error = '';
my $try = try { die 'In try with naive catch' } catch { $error = $_; };
print Data::Dumper->Dump([$try, $error], [qw[try error]]), "\n=====\n";
[...]

$try = 'In try with naive catch at local/test/052.pl line 11.
';
$error = 'In try with naive catch at local/test/052.pl line 11.
';
[...]

Indeed, checking the code as of 5.8.8, and the most recent source
under http://search.cpan.org/~doy/Try-Tiny-0.11/lib/Try/Tiny.pm, catch
is invoked with

for ($error) {
return $catch->($error);
}

(I think it's stupid as all hell, but whatever.)

The idea behind that is obviously that the catching subroutine might
be able to handle the error (Perl still supports real exception
objects) and should thus have the option to inform the caller that no
error occurred.
So I think I can
replace

some_lhs = eval { body };
# uses of [email protected]

with

my $error;
some_lhs = try { body } catch { $error = $_; return };
# uses of $error

Is that right?

You can also insert a system('perl -c "sleep(86400);"') in
any place there and the result will be that the working code
still works, just in a less efficient way. Actually, using the
sleep-invocation is a much more efficient way to burn time than
downloading $random_crap from CPAN whose only purpose is to "work
around" what some guy didn't understand about Perl exception handling
in particular and the concept of using exceptions for error handling in
general. You don't even have to take my word for that, it's also all
spelled out in the Perl 5.14.0 release notes available here:

http://perldoc.perl.org/perl5140delta.html#Exception-Handling
 
T

Tim McDaniel

[email protected] (Tim McDaniel) said:
[Try::Tiny: catch returns a value]
(I think it's stupid as all hell, but whatever.)

The idea behind that is obviously that the catching subroutine might
be able to handle the error (Perl still supports real exception
objects) and should thus have the option to inform the caller that no
error occurred.

Good point. It just makes it a touch annoying for *my particular*
case, a drop-in replacement for eval, but I quite take your point
about other cases.
all spelled out in the Perl 5.14.0 release notes available here:

My workplace is on an older version of Perl, I can't upgrade it, and I
don't know when they'll upgrade.
Actually, using the sleep-invocation is a much more efficient way to
burn time than downloading $random_crap from CPAN

Try::Tiny is a long-standing package and not uncommon package, hardly
"random crap".
whose only purpose is to "work around" what some guy didn't
understand about Perl exception handling in particular and the
concept of using exceptions for error handling in general.

What do I do to use raw Perl to get reliable exceptions in older Perls?
 
R

Rainer Weikusat

[...]

all spelled out in the Perl 5.14.0 release notes available here:

My workplace is on an older version of Perl, I can't upgrade it, and I
don't know when they'll upgrade.

In this case, this text provides some nice documentation regarding
what the actual gotchas with eval and [email protected] are. There are two possible
problem cases: Provided that object destructors are executed during
exception unwinding occurring while existing from the eval,

- [email protected] will be cleared when code running from a destructor calls
eval

- [email protected] will be overwritten when code running from such a
destructor throws an exception itself

Both issues can be avoided by adding a local [email protected] at the start of all
destructors which might either die or use eval.
Try::Tiny is a long-standing package and not uncommon package, hardly
"random crap".

The copyright notice says 2009 which means it is a good fourteen years
younger than the facility it is supposed to fix. And neither "it is
old" (which it isn't) nor "many people like it" are indicators for any
particular technical quality.
 
Ad

Advertisements

R

Rainer Weikusat

Dr.Ruud said:
That should be written as:

eval "$string; 1" or die [email protected] || 'zombie error';

Depending on the contents of $string, this may either clobber the
result evaluating the code (because the eval will always return 1 if
no error occurred and the string didn't cause a return) or cause a
gratuitious failure (if $string contains a 'return $something' and this
$something can be zero).
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top