NAME
Evo::Eval
VERSION
version 0.0245
SYNOPSYS
use Evo '-Eval *';
try { die "Error" } sub($e) { print "Catched: $e" };
# try_fn, catch_fn, finally_fn
my $res;
$res = try sub {...}, sub {...}, sub {...};
$res = try sub {...}, sub {...};
$res = 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
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 = try sub { return "ok" }, sub {...}, sub { print "fin; " };
say "result: ", $res;
# fin; result: catched
$res = 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 = 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 = try sub { 1 }, sub {...}, sub { die "FinError\n" };
Deals correctly with wantarray
# 1;2;3
local $, = ';';
say try sub { wantarray ? (1, 2, 3) : 'One-Two-Three' }, sub {...};
# One-Two-Three
say scalar 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.