NAME
Evo::Lib
VERSION
version 0.0405
FUNCTIONS
steady_time
Return an array contains only uniq elements
uniq(@args)
Return an array contains only uniq elements
strict_opts($level, $hash, @keys)
sub foo3(%opts) { strict_opts(\%opts, qw(foo bar)); }
sub foo2(%opts) { strict_opts(\%opts, [qw(foo bar)], 1); }
Get a $hash
and return values in order defined by @keys
. If there are superfluous keys in hash, throw an error. This will help you to protect your functions from bugs "passing wrong keys"
$level
(the last argument if the second is array ref) determines how many frames to skip. By default it's 1
try
The behaviour is just like JS's try catch finally with one exception: return statement in finally block doesn't matter, because in perl every subroutine returns something (and because it's more "as expected") and it't impossible to distinguish return/no return
use Evo '-Lib try';
# try + catch
try { die "MyError" } sub($e) { say "Catched: $e" };
# try + catch + finally
try sub { die "MyError" }, sub($e) { say "Catched: $e" }, sub { say "Finally" };
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 {...};
Also you should pay attention that it doesn't localize $@
. That's intentionally
Motivation
There is a similar and popular Try::Tiny, but it has a flaw: it can't catch errors in finally block. Which isn't unacceptable for module written for exception handling
use Evo 'Try::Tiny; -Lib try:evo_try; Test::More';
# try tiny can't catches errors here because of flaw in module design
eval {
try {} catch { } finally { die "foo\n" };
};
is $@, "foo\n", "Try::Tiny";
# Evo's try catches an error correctly
eval {
evo_try sub { }, sub { }, sub { die "foo\n" };
};
is $@, "foo\n", "Evo";
Also this module is much faster (both PP and XS) and more tiny(~30 lines of code in PP). The only disadvantage is (is it?) it doesn't simulate "catch, finally" keyword. But for me it's not a problem
eval_want
Invokes a last argument with the context of the first void: undef, scalar: '', list: 1
, 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
Mostly for internal purposes to deal correctly with wantarray
and for creating a spy. Short: it allows to intercept execution flow without loosing a context
use Evo '-Lib eval_want';
sub add2($val) { $val + 2 }
sub create_spy($fn) {
sub {
warn "[spy] context: ", wantarray, "; args: ", join ';', @_;
my $call = eval_want(wantarray, @_, $fn) or die $@;
$call->();
};
}
my $spy = create_spy(\&add2);
say $spy->(10);
As you can se, we just pass given context wantarray
to the eval_want
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.