NAME

Evo::Eval

VERSION

version 0.0241

SYNOPSYS

use Evo '-Eval *';

eval_try { die "Error" } sub($e) { print "Catched: $e" };

# try_fn, catch_fn, finally_fn
my $res;
$res = eval_try sub {...}, sub {...}, sub {...};
$res = eval_try sub {...}, sub {...};
$res = eval_try sub {...}, undef, sub {...};

Classarison with alternatives

with Try::Tiny

Try::Tiny is very similar and PP too, but has design flaw, and can't catch this case:

use Try::Tiny;
sub foo { try {} finally { die "Foo" }; }

eval { foo() };
warn "Shouldn't be here";

Instead of throwing an exception, it can only report it to STDERR.

Also because Evo::Eval doesn't try to pretend "blocks", it work's 3-5 times faster than Try::Tiny and is much more "tiny" (see source code)

with TryCatch

TryCatch is 3-4 times faster, but has many dependencies written in C, doesn't support finally and has a lot of code compared to this module

with Guard

Guard is written in C and has the same flaw as Try::Tiny - can't deal with exceptions.

FUNCTION

eval_try

The semantic is similar to JS "try catch finally" block except returned value of finally block doesn't matter.

Can be used as replacement of Guard.pm, Try::Tiny.pm and so on, because solves their main problems If "finally" block throws an error, they can't catch it.

This module deal with this case the right way: If "finally" block throws an error, the exception will be thrown.

It's behaviour is just like JS's try catch finally with one exception: return statement in finally block doesn't matter, because in perl every subroitine returns something (and because it's more "as expected")

Brief description

Firstly "try_fn" will be executed. If it throws an error, "catch_fn" will be executed with that exception as an argument and perl won't die. "finally_fn", if exists, will be always executed but the return value of finally_fn will be ignored.

Examples

# fin; result: ok
my $res = eval_try sub { return "ok" }, sub {...}, sub { print "fin; " };
say "result: ", $res;

# fin; result: catched
$res = eval_try sub { die "Error\n" }, sub { return "catched" }, sub { print "fin; " };
say "result: ", $res;

"Catch" block can be skipped if we're interesting only in "finally"

# print fin than dies with "Error" in $@
$res = eval_try sub { die "Error\n" }, undef, sub { print "fin\n" };

If "finally" fn throws an exception, it will be rethrown as expected

# die in finally block with "FinError\n" in $@
$res = eval_try sub { 1 }, sub {...}, sub { die "FinError\n" };

Deals correctly with wantarray

# 1;2;3
local $, = ';';
say eval_try sub { wantarray ? (1, 2, 3) : 'One-Two-Three' }, sub {...};

# One-Two-Three
say scalar eval_try sub { wantarray ? (1, 2, 3) : 'One-Two-Three' }, sub {...};

eval_want

use Evo '-Eval *; -Want *';
my $call = eval_want WANT_LIST, sub { return (1, 2, 3) };
say $call->result;

Mostly is for internal purposes to deal correctly with wantarray

Invokes a last argument with the context of the first argument(see Evo::Want), passing remaining arguments. If the function throws an error, returns nothing and sets <$@>. So returned value can answer the question was an invocation successfull or not

use Evo '-Eval *';

sub proxy {
  my $next = pop;
  my $call = eval_want(wantarray, @_, $next) or die $@;
  $call->result;
}

my @arr = proxy(1, 2, sub { say "want_list" if wantarray; return (1, 2) });
say @arr;

AUTHOR

alexbyk.com

COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by alexbyk.

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