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, $@], [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 $@

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 $@,
I think I can get away with

try { eval string_value; die $@ if $@ } catch { $error = $_; return }

Anyone see a problem with that?
 
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 $@

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 $@ are. There are two possible
problem cases: Provided that object destructors are executed during
exception unwinding occurring while existing from the eval,

- $@ will be cleared when code running from a destructor calls
eval

- $@ will be overwritten when code running from such a
destructor throws an exception itself

Both issues can be avoided by adding a local $@ 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.
 
R

Rainer Weikusat

Dr.Ruud said:
That should be written as:

eval "$string; 1" or die $@ || '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).
 

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

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top